diff --git a/app/src/Server.js b/app/src/Server.js index 9715372b..27467ed9 100644 --- a/app/src/Server.js +++ b/app/src/Server.js @@ -41,7 +41,7 @@ dependencies: { * @license For commercial or closed source, contact us at license.mirotalk@gmail.com or purchase directly via CodeCanyon * @license CodeCanyon: https://codecanyon.net/item/mirotalk-sfu-webrtc-realtime-video-conferences/40769970 * @author Miroslav Pejic - miroslav.pejic.85@gmail.com - * @version 1.3.73 + * @version 1.3.74 * */ @@ -109,6 +109,9 @@ const jwtCfg = { const hostCfg = { protected: config.host.protected, user_auth: config.host.user_auth, + users_from_db: config.host.users_from_db, + users_api_endpoint: config.host.users_api_endpoint, + users_api_secret_key: config.host.users_api_secret_key, users: config.host.users, authenticated: !config.host.protected, }; @@ -305,7 +308,7 @@ function startServer() { }); // no room name specified to join || direct join - app.get('/join/', (req, res) => { + app.get('/join/', async (req, res) => { if (Object.keys(req.query).length > 0) { log.debug('Direct Join', req.query); @@ -326,7 +329,7 @@ function startServer() { const { username, password, presenter } = checkXSS(jwt.verify(token, jwtCfg.JWT_KEY)); peerUsername = username; peerPassword = password; - isPeerValid = isAuthPeer(username, password); + isPeerValid = await isAuthPeer(username, password); isPeerPresenter = presenter === '1' || presenter === 'true'; } catch (err) { log.error('Direct Join JWT error', { error: err.message, token: token }); @@ -419,13 +422,13 @@ function startServer() { // #################################################### // handle login on host protected - app.post(['/login'], (req, res) => { + app.post(['/login'], async (req, res) => { const ip = getIP(req); log.debug(`Request login to host from: ${ip}`, req.body); const { username, password } = checkXSS(req.body); - const isPeerValid = isAuthPeer(username, password); + const isPeerValid = await isAuthPeer(username, password); if (hostCfg.protected && isPeerValid && !hostCfg.authenticated) { const ip = getIP(req); @@ -1169,7 +1172,7 @@ function startServer() { try { const { username, password, presenter } = checkXSS(jwt.verify(peer_token, jwtCfg.JWT_KEY)); - const isPeerValid = isAuthPeer(username, password); + const isPeerValid = await isAuthPeer(username, password); is_presenter = presenter === '1' || presenter === 'true'; @@ -1699,8 +1702,24 @@ function startServer() { } } - function isAuthPeer(username, password) { - return hostCfg.users && hostCfg.users.some((user) => user.username === username && user.password === password); + async function isAuthPeer(username, password) { + if (hostCfg.users_from_db && hostCfg.users_api_endpoint) { + try { + const response = await axios.post(hostCfg.users_api_endpoint, { + email: username, + password: password, + api_secret_key: hostCfg.users_api_secret_key, + }); + return response.data && response.data.message === true; + } catch (error) { + log.error('AXIOS isAuthPeer error', error.message); + return false; + } + } else { + return ( + hostCfg.users && hostCfg.users.some((user) => user.username === username && user.password === password) + ); + } } function getActiveRooms() { diff --git a/app/src/config.template.js b/app/src/config.template.js index d97599d4..5cbba6b4 100644 --- a/app/src/config.template.js +++ b/app/src/config.template.js @@ -57,10 +57,14 @@ module.exports = { /* Host Protection (default: false) To enhance host security, enable host protection - user auth and provide valid - usernames and passwords in the users array. + usernames and passwords in the users array or active users_from_db using users_api_endpoint for check. */ protected: false, user_auth: false, + users_from_db: false, + //users_api_endpoint: 'http://localhost:9000/api/v1/user/isAuth', + users_api_endpoint: 'https://webrtc.mirotalk.com/api/v1/user/isAuth', + users_api_secret_key: '91bbfac3-5e39-4583-9123-883b72be505c', users: [ { username: 'username', diff --git a/package.json b/package.json index 74e70b23..732fc2ee 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mirotalksfu", - "version": "1.3.73", + "version": "1.3.74", "description": "WebRTC SFU browser-based video calls", "main": "Server.js", "scripts": { @@ -38,8 +38,8 @@ "author": "Miroslav Pejic", "license": "AGPL-3.0", "dependencies": { - "@sentry/integrations": "7.101.0", - "@sentry/node": "7.101.0", + "@sentry/integrations": "7.102.0", + "@sentry/node": "7.102.0", "axios": "^1.6.7", "body-parser": "1.20.2", "colors": "1.4.0", diff --git a/public/js/Room.js b/public/js/Room.js index a06d5489..d3ab7561 100644 --- a/public/js/Room.js +++ b/public/js/Room.js @@ -11,7 +11,7 @@ if (location.href.substr(0, 5) !== 'https') location.href = 'https' + location.h * @license For commercial or closed source, contact us at license.mirotalk@gmail.com or purchase directly via CodeCanyon * @license CodeCanyon: https://codecanyon.net/item/mirotalk-sfu-webrtc-realtime-video-conferences/40769970 * @author Miroslav Pejic - miroslav.pejic.85@gmail.com - * @version 1.3.73 + * @version 1.3.74 * */ diff --git a/public/js/RoomClient.js b/public/js/RoomClient.js index 933cff90..e5201609 100644 --- a/public/js/RoomClient.js +++ b/public/js/RoomClient.js @@ -9,7 +9,7 @@ * @license For commercial or closed source, contact us at license.mirotalk@gmail.com or purchase directly via CodeCanyon * @license CodeCanyon: https://codecanyon.net/item/mirotalk-sfu-webrtc-realtime-video-conferences/40769970 * @author Miroslav Pejic - miroslav.pejic.85@gmail.com - * @version 1.3.73 + * @version 1.3.74 * */ @@ -4185,27 +4185,21 @@ class RoomClient { } async syncRecordingInCloud(data) { - const arrayBuffer = data; + const arrayBuffer = await data.arrayBuffer(); const chunkSize = rc.recSyncChunkSize; - const fileReader = new FileReader(); - fileReader.readAsArrayBuffer(arrayBuffer); - fileReader.onload = async (event) => { - const arrayBuffer = event.target.result; - const totalChunks = Math.ceil(arrayBuffer.byteLength / chunkSize); - for (let chunkIndex = 0; chunkIndex < totalChunks; chunkIndex++) { - const chunk = arrayBuffer.slice(chunkIndex * chunkSize, (chunkIndex + 1) * chunkSize); - try { - await axios.post('/recSync?fileName=' + rc.recServerFileName, chunk, { - headers: { - 'Content-Type': 'application/octet-stream', - 'Content-Length': chunk.length, - }, - }); - } catch (error) { - console.error('Error syncing chunk:', error.message); - } + const totalChunks = Math.ceil(arrayBuffer.byteLength / chunkSize); + for (let chunkIndex = 0; chunkIndex < totalChunks; chunkIndex++) { + const chunk = arrayBuffer.slice(chunkIndex * chunkSize, (chunkIndex + 1) * chunkSize); + try { + await axios.post('/recSync?fileName=' + rc.recServerFileName, chunk, { + headers: { + 'Content-Type': 'application/octet-stream', + }, + }); + } catch (error) { + console.error('Error syncing chunk:', error.message); } - }; + } } handleMediaRecorderStop(evt) {