bigbluebutton-Github/bigbluebutton-html5/imports/ui/components/connection-manager/startup-data-fetch/component.tsx
schrd 64e43e4331
fix(core): 3.0 cluster setup (#20439)
* Add graphql API endpoint to BBB API

This parameter will be required for the HTML5 client to discover the API
endpoint of the GraphQL API so it can fetch its settings.

* Fix: ensure API calls are headed towards the BBB Server

In a cluster setup the URL that is visible in the browser is different
from the URL of the BBB Server.

The clients needs to contact the BBB server to retrieve information
about the graphQL websocket and the graphql API.

This patch adds the GraphQL API endpoint to the BBB API and changes the
Client to use it.

* Make GraphQL API endpoint configurable

The default value should work for single node and cluster setups

* Update docs to reflect changes required by cluster setup

* fix eslint and typescript errors

* Fix cluster setup docs

- add missing parts for hasura
- use consistent domain example.com

* rename variable

Co-authored-by: Gustavo Trott <gustavo@trott.com.br>

* rename variable

Co-authored-by: Gustavo Trott <gustavo@trott.com.br>

* rename variable

Co-authored-by: Gustavo Trott <gustavo@trott.com.br>

* Update bigbluebutton-web/grails-app/controllers/org/bigbluebutton/web/controllers/ApiController.groovy

Co-authored-by: Gustavo Trott <gustavo@trott.com.br>

* Update bigbluebutton-web/grails-app/conf/bigbluebutton.properties

Co-authored-by: Gustavo Trott <gustavo@trott.com.br>

---------

Co-authored-by: Daniel Schreiber <daniel.schreiber@hrz.tu-chemnitz.de>
Co-authored-by: Gustavo Trott <gustavo@trott.com.br>
2024-06-17 14:26:13 -04:00

124 lines
3.5 KiB
TypeScript

import React, { useEffect } from 'react';
import { Session } from 'meteor/session';
import { v4 as uuid } from 'uuid';
import { ErrorScreen } from '../../error-screen/component';
import LoadingScreen from '../../common/loading-screen/component';
const connectionTimeout = 60000;
interface Response {
meeting_clientSettings: Array<{
askForFeedbackOnLogout: boolean,
allowDefaultLogoutUrl: boolean,
learningDashboardBase: string,
fallbackLocale: string,
fallbackOnEmptyString: boolean,
mediaTag: string,
clientLog: {
server: {
level: string,
enabled: boolean
},
console: {
level: string,
enabled: true
},
external: {
url: string,
level: string,
logTag: string,
method: string,
enabled: boolean,
flushOnClose: boolean,
throttleInterval: number,
}
}
}>
}
interface StartupDataFetchProps {
children: React.ReactNode;
}
const StartupDataFetch: React.FC<StartupDataFetchProps> = ({
children,
}) => {
const [settingsFetched, setSettingsFetched] = React.useState<boolean>(false);
const [error, setError] = React.useState<string>('');
const timeoutRef = React.useRef<ReturnType<typeof setTimeout>>();
const [loading, setLoading] = React.useState<boolean>(false);
useEffect(() => {
setLoading(true);
timeoutRef.current = setTimeout(() => {
setError('Timeout on fetching startup data');
setLoading(false);
}, connectionTimeout);
const clientSessionUUID = uuid();
sessionStorage.setItem('clientSessionUUID', clientSessionUUID);
const urlParams = new URLSearchParams(window.location.search);
const sessionToken = urlParams.get('sessionToken');
if (!sessionToken) {
setError('Missing session token');
setLoading(false);
return;
}
const pathMatch = window.location.pathname.match('^(.*)/html5client/join$');
if (pathMatch == null) {
throw new Error('Failed to match BBB client URI');
}
const serverPathPrefix = pathMatch[1];
fetch(`https://${window.location.hostname}${serverPathPrefix}/bigbluebutton/api`, {
headers: {
'Content-Type': 'application/json',
},
}).then((resp) => resp.json())
.then((data) => {
const url = `${data.response.graphqlApiUrl}/clientStartupSettings/?sessionToken=${sessionToken}`;
fetch(url, { method: 'get', credentials: 'include' })
.then((resp) => resp.json())
.then((data: Response) => {
const settings = data.meeting_clientSettings[0];
sessionStorage.setItem('clientStartupSettings', JSON.stringify(settings || {}));
setSettingsFetched(true);
clearTimeout(timeoutRef.current);
setLoading(false);
}).catch(() => {
Session.set('errorMessageDescription', 'meeting_ended');
setError('Error fetching startup data');
setLoading(false);
});
}).catch((error) => {
setLoading(false);
throw new Error('Error fetching GraphQL URL: '.concat(error.message || ''));
});
}, []);
return (
<>
{settingsFetched ? children : null}
{error
? (
<ErrorScreen
endedReason={error}
code={403}
/>
)
: null}
{loading
? (
<LoadingScreen>
<div style={{ display: 'none' }}>
Loading...
</div>
</LoadingScreen>
)
: null}
</>
);
};
export default StartupDataFetch;