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