From 5a3649791bd8923db7599208362ea69f0e7d448e Mon Sep 17 00:00:00 2001
From: Tainan Felipe <tainanfelipe214@gmail.com>
Date: Wed, 14 Nov 2018 15:11:10 -0200
Subject: [PATCH] Transform joinRouterHandler and aunthenticatedRouteHandler in
 components

---
 bigbluebutton-html5/client/main.jsx           |  30 ++--
 .../imports/startup/client/auth.js            | 134 ------------------
 .../authenticated-handler/component.jsx       |  90 ++++++++++++
 .../ui/components/join-handler/component.jsx  | 121 ++++++++++++++++
 .../ui/components/meeting-ended/component.jsx |  17 ++-
 5 files changed, 235 insertions(+), 157 deletions(-)
 delete mode 100755 bigbluebutton-html5/imports/startup/client/auth.js
 create mode 100644 bigbluebutton-html5/imports/ui/components/authenticated-handler/component.jsx
 create mode 100644 bigbluebutton-html5/imports/ui/components/join-handler/component.jsx

diff --git a/bigbluebutton-html5/client/main.jsx b/bigbluebutton-html5/client/main.jsx
index 683d148e23..7eea3c5c44 100755
--- a/bigbluebutton-html5/client/main.jsx
+++ b/bigbluebutton-html5/client/main.jsx
@@ -1,16 +1,13 @@
 /* eslint no-unused-vars: 0 */
 import React from 'react';
 import { Meteor } from 'meteor/meteor';
-import { Session } from 'meteor/session';
 import { render } from 'react-dom';
 import logger from '/imports/startup/client/logger';
-import { joinRouteHandler, authenticatedRouteHandler } from '/imports/startup/client/auth';
 import Base from '/imports/startup/client/base';
-import LoadingScreen from '/imports/ui/components/loading-screen/component';
+import JoinHandler from '/imports/ui/components/join-handler/component';
+import AuthenticatedHandler from '/imports/ui/components/authenticated-handler/component';
 
 Meteor.startup(() => {
-  render(<LoadingScreen />, document.getElementById('app'));
-
   // Logs all uncaught exceptions to the client logger
   window.addEventListener('error', (e) => {
     const { stack } = e.error;
@@ -26,19 +23,12 @@ Meteor.startup(() => {
   });
 
   // TODO make this a Promise
-  joinRouteHandler((value, error) => {
-    if (error) {
-      logger.error(`User faced [${value}] on main.joinRouteHandler. Error was:`, JSON.stringify(error));
-    } else {
-      logger.info(`User successfully went through main.joinRouteHandler with [${value}].`);
-    }
-    authenticatedRouteHandler(() => {
-      // set defaults
-      Session.set('isChatOpen', false);
-      Session.set('idChatOpen', '');
-      Session.set('isMeetingEnded', false);
-      Session.get('breakoutRoomIsOpen', false);
-      render(<Base />, document.getElementById('app'));
-    });
-  });
+  render(
+    <JoinHandler >
+      <AuthenticatedHandler>
+        <Base />
+      </AuthenticatedHandler>
+    </JoinHandler>,
+    document.getElementById('app'),
+  );
 });
diff --git a/bigbluebutton-html5/imports/startup/client/auth.js b/bigbluebutton-html5/imports/startup/client/auth.js
deleted file mode 100755
index 6f50e762c6..0000000000
--- a/bigbluebutton-html5/imports/startup/client/auth.js
+++ /dev/null
@@ -1,134 +0,0 @@
-import Auth from '/imports/ui/services/auth';
-import { setCustomLogoUrl } from '/imports/ui/components/user-list/service';
-import { log, makeCall } from '/imports/ui/services/api';
-import deviceInfo from '/imports/utils/deviceInfo';
-import logger from '/imports/startup/client/logger';
-import { Session } from 'meteor/session';
-
-// disconnected and trying to open a new connection
-const STATUS_CONNECTING = 'connecting';
-
-const setError = (errorCode) => {
-  Session.set('hasError', true);
-  Session.set('codeError', errorCode);
-};
-
-export function joinRouteHandler(callback) {
-  const urlParams = new URLSearchParams(window.location.search);
-  const sessionToken = urlParams.get('sessionToken');
-
-  if (!sessionToken) {
-    setError('404');
-    callback('failed - no sessionToken', urlParams);
-  }
-
-  // Old credentials stored in memory were being used when joining a new meeting
-  Auth.clearCredentials();
-
-  // use enter api to get params for the client
-  const url = `/bigbluebutton/api/enter?sessionToken=${sessionToken}`;
-
-  fetch(url, { credentials: 'same-origin' })
-    .then(response => response.json())
-    .then(({ response }) => {
-      const {
-        returncode, meetingID, internalUserID, authToken, logoutUrl, customLogoURL,
-        externUserID, fullname, confname, customdata,
-      } = response;
-
-      if (returncode === 'FAILED') {
-        setError('404');
-        callback('failed during enter API call', response);
-      } else {
-        setCustomLogoUrl(customLogoURL);
-
-        if (customdata.length) {
-          makeCall('addUserSettings', meetingID, internalUserID, customdata);
-        }
-
-        Auth.set(
-          meetingID, internalUserID, authToken, logoutUrl,
-          sessionToken, fullname, externUserID, confname,
-        );
-
-        Session.set('isUserListOpen', deviceInfo.type().isPhone);
-        const userInfo = window.navigator;
-
-        // Browser information is sent once on startup
-        // Sent here instead of Meteor.startup, as the
-        // user might not be validated by then, thus user's data
-        // would not be sent with this information
-        const clientInfo = {
-          language: userInfo.language,
-          userAgent: userInfo.userAgent,
-          screenSize: { width: window.screen.width, height: window.screen.height },
-          windowSize: { width: window.innerWidth, height: window.innerHeight },
-          bbbVersion: Meteor.settings.public.app.bbbServerVersion,
-          location: window.location.href,
-        };
-
-        logger.info(clientInfo);
-
-        callback('all is good', null);
-      }
-    });
-}
-
-export function logoutRouteHandler() {
-  Auth.logout()
-    .then((logoutURL = window.location.origin) => {
-      const protocolPattern = /^((http|https):\/\/)/;
-
-      window.location.href =
-        protocolPattern.test(logoutURL) ?
-          logoutURL :
-          `http://${logoutURL}`;
-    });
-}
-
-/**
- * Check if should revalidate the auth
- * @param {Object} status
- * @param {String} lastStatus
- */
-export function shouldAuthenticate(status, lastStatus) {
-  return lastStatus != null && lastStatus === STATUS_CONNECTING && status.connected;
-}
-
-/**
- * Check if the isn't the first connection try, preventing to authenticate on login.
- * @param {Object} status
- * @param {string} lastStatus
- */
-export function updateStatus(status, lastStatus) {
-  return status.retryCount > 0 && lastStatus !== STATUS_CONNECTING ? status.status : lastStatus;
-}
-
-function _addReconnectObservable() {
-  let lastStatus = null;
-
-  Tracker.autorun(() => {
-    lastStatus = updateStatus(Meteor.status(), lastStatus);
-
-    if (shouldAuthenticate(Meteor.status(), lastStatus)) {
-      Auth.authenticate(true);
-      lastStatus = Meteor.status().status;
-    }
-  });
-}
-
-export function authenticatedRouteHandler(callback) {
-  if (Auth.loggedIn) {
-    callback();
-  }
-
-  _addReconnectObservable();
-
-  Auth.authenticate()
-    .then(callback)
-    .catch((reason) => {
-      log('error', reason);
-      setError(reason.error);
-      callback();
-    });
-}
diff --git a/bigbluebutton-html5/imports/ui/components/authenticated-handler/component.jsx b/bigbluebutton-html5/imports/ui/components/authenticated-handler/component.jsx
new file mode 100644
index 0000000000..96ebd5d943
--- /dev/null
+++ b/bigbluebutton-html5/imports/ui/components/authenticated-handler/component.jsx
@@ -0,0 +1,90 @@
+import React, { Component } from 'react';
+import { Session } from 'meteor/session';
+import _ from 'lodash';
+import { log } from '/imports/ui/services/api';
+import Auth from '/imports/ui/services/auth';
+import LoadingScreen from '/imports/ui/components/loading-screen/component';
+
+const STATUS_CONNECTING = 'connecting';
+
+class AuthenticatedHandler extends Component {
+  static setError(codeError) {
+    Session.set('hasError', true);
+    if (codeError) Session.set('codeError', codeError);
+  }
+  static shouldAuthenticate(status, lastStatus) {
+    return lastStatus != null && lastStatus === STATUS_CONNECTING && status.connected;
+  }
+
+  static updateStatus(status, lastStatus) {
+    return status.retryCount > 0 && lastStatus !== STATUS_CONNECTING ? status.status : lastStatus;
+  }
+
+  static addReconnectObservable() {
+    let lastStatus = null;
+
+    Tracker.autorun(() => {
+      lastStatus = AuthenticatedHandler.updateStatus(Meteor.status(), lastStatus);
+
+      if (AuthenticatedHandler.shouldAuthenticate(Meteor.status(), lastStatus)) {
+        Auth.authenticate(true);
+        lastStatus = Meteor.status().status;
+      }
+    });
+  }
+  static authenticatedRouteHandler(callback) {
+    if (Auth.loggedIn) {
+      callback();
+    }
+
+    AuthenticatedHandler.addReconnectObservable();
+
+    Auth.authenticate()
+      .then(callback)
+      .catch((reason) => {
+        log('error', reason);
+        AuthenticatedHandler.setError(reason.error);
+        callback();
+      });
+  }
+  constructor(props) {
+    super(props);
+    this.changeState = this.changeState.bind(this);
+    this.state = {
+      authenticated: false,
+    };
+  }
+
+  componentDidMount() {
+    AuthenticatedHandler.authenticatedRouteHandler((value, error) => {
+      if (error) AuthenticatedHandler.setError(error);
+      this.changeState(true);
+    });
+  }
+
+  changeState(state) {
+    this.setState({ authenticated: state });
+  }
+
+  render() {
+    const {
+      children,
+    } = this.props;
+    const {
+      authenticated,
+    } = this.state;
+
+    Session.set('isChatOpen', false);
+    Session.set('idChatOpen', '');
+    Session.set('isMeetingEnded', false);
+    Session.set('isPollOpen', false);
+    Session.set('breakoutRoomIsOpen', false);
+
+    return authenticated
+      ? children
+      : (<LoadingScreen />);
+  }
+}
+
+
+export default AuthenticatedHandler;
diff --git a/bigbluebutton-html5/imports/ui/components/join-handler/component.jsx b/bigbluebutton-html5/imports/ui/components/join-handler/component.jsx
new file mode 100644
index 0000000000..87602df009
--- /dev/null
+++ b/bigbluebutton-html5/imports/ui/components/join-handler/component.jsx
@@ -0,0 +1,121 @@
+import React, { Component } from 'react';
+import { Session } from 'meteor/session';
+import _ from 'lodash';
+import Auth from '/imports/ui/services/auth';
+import { setCustomLogoUrl } from '/imports/ui/components/user-list/service';
+import { makeCall } from '/imports/ui/services/api';
+import deviceInfo from '/imports/utils/deviceInfo';
+import logger from '/imports/startup/client/logger';
+import LoadingScreen from '/imports/ui/components/loading-screen/component';
+
+class JoinHandler extends Component {
+  static setError(codeError) {
+    Session.set('hasError', true);
+    if (codeError) Session.set('codeError', codeError);
+  }
+  constructor(props) {
+    super(props);
+    this.fetchTolken = this.fetchTolken.bind(this);
+    this.changeToJoin = this.changeToJoin.bind(this);
+
+    this.state = {
+      joined: false,
+    };
+  }
+
+  componentDidMount() {
+    this.fetchTolken();
+  }
+
+  changeToJoin(bool) {
+    this.setState({ joined: bool });
+  }
+
+  fetchTolken() {
+    const urlParams = new URLSearchParams(window.location.search);
+    const sessionToken = urlParams.get('sessionToken');
+    if (!sessionToken) {
+      JoinHandler.setError('404');
+    }
+
+    // Old credentials stored in memory were being used when joining a new meeting
+    Auth.clearCredentials();
+    const logUserInfo = () => {
+      const userInfo = window.navigator;
+
+      // Browser information is sent once on startup
+      // Sent here instead of Meteor.startup, as the
+      // user might not be validated by then, thus user's data
+      // would not be sent with this information
+      const clientInfo = {
+        language: userInfo.language,
+        userAgent: userInfo.userAgent,
+        screenSize: { width: window.screen.width, height: window.screen.height },
+        windowSize: { width: window.innerWidth, height: window.innerHeight },
+        bbbVersion: Meteor.settings.public.app.bbbServerVersion,
+        location: window.location.href,
+      };
+
+      logger.info(clientInfo);
+    };
+
+    const setAuth = (resp) => {
+      const {
+        meetingID, internalUserID, authToken, logoutUrl,
+        fullname, externUserID, confname,
+      } = resp;
+      Auth.set(
+        meetingID, internalUserID, authToken, logoutUrl,
+        sessionToken, fullname, externUserID, confname,
+      );
+      return resp;
+    };
+
+    const setLogoURl = (resp) => {
+      setCustomLogoUrl(resp.customLogoURL);
+      return resp;
+    };
+
+    const setCustomData = (resp) => {
+      const {
+        meetingID, internalUserID, customdata,
+      } = resp;
+
+      if (customdata.length) {
+        makeCall('addUserSettings', meetingID, internalUserID, customdata);
+      }
+      return resp;
+    };
+    // use enter api to get params for the client
+    const url = `/bigbluebutton/api/enter?sessionToken=${sessionToken}`;
+
+    const validAuth = new Promise((resolve, reject) => {
+      fetch(url, { credentials: 'same-origin' })
+        .then(response => response.json())
+        .then(({ response }) => response)
+        .then((resp) => {
+          if (resp.returncode !== 'FAILED') return resolve(resp);
+          const e = new Error('Session not found');
+          return reject(e);
+        });
+    });
+
+    validAuth
+      .then(setCustomData)
+      .then(setAuth)
+      .then(setLogoURl)
+      .then(() => Session.set('isUserListOpen', deviceInfo.type().isPhone))
+      .then(logUserInfo)
+      .finally(() => this.changeToJoin(true));
+  }
+
+  render() {
+    const { children } = this.props;
+    const { joined } = this.state;
+    return joined ?
+      children :
+      (<LoadingScreen />);
+  }
+}
+
+export default JoinHandler;
diff --git a/bigbluebutton-html5/imports/ui/components/meeting-ended/component.jsx b/bigbluebutton-html5/imports/ui/components/meeting-ended/component.jsx
index f5e93483f9..1b052589c9 100755
--- a/bigbluebutton-html5/imports/ui/components/meeting-ended/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/meeting-ended/component.jsx
@@ -4,7 +4,6 @@ import { defineMessages, injectIntl } from 'react-intl';
 import Auth from '/imports/ui/services/auth';
 import Button from '/imports/ui/components/button/component';
 import getFromUserSettings from '/imports/ui/services/users-settings';
-import { logoutRouteHandler } from '/imports/startup/client/auth';
 import Rating from './rating/component';
 import { styles } from './styles';
 
@@ -73,6 +72,18 @@ class MeetingEnded extends React.PureComponent {
     return comment;
   }
 
+  static logoutRouteHandler() {
+    Auth.logout()
+      .then((logoutURL = window.location.origin) => {
+        const protocolPattern = /^((http|https):\/\/)/;
+
+        window.location.href =
+          protocolPattern.test(logoutURL) ?
+            logoutURL :
+            `http://${logoutURL}`;
+      });
+  }
+
   constructor(props) {
     super(props);
     this.state = {
@@ -94,7 +105,7 @@ class MeetingEnded extends React.PureComponent {
     } = this.state;
 
     if (selected <= 0) {
-      logoutRouteHandler();
+      MeetingEnded.logoutRouteHandler();
       return;
     }
 
@@ -116,7 +127,7 @@ class MeetingEnded extends React.PureComponent {
 
     fetch(url, options)
       .finally(() => {
-        logoutRouteHandler();
+        MeetingEnded.logoutRouteHandler();
       });
   }
 
-- 
GitLab