diff --git a/.env.template b/.env.template index f453fa7..484bc21 100644 --- a/.env.template +++ b/.env.template @@ -17,6 +17,11 @@ TURN_SERVER_URL=turn:a.relay.metered.ca:443 TURN_SERVER_USERNAME=e8dd65b92c62d3e36cafb807 TURN_SERVER_CREDENTIAL=uWdWNmkhvyqTEswO +# Room + +ROOM_PASSWORD_ENABLED=false # true or false +ROOM_PASSWORD='123456789' + # API API_KEY_SECRET=call_me_api_key_secret # change me diff --git a/app/server.js b/app/server.js index 8aeb278..44f18c5 100755 --- a/app/server.js +++ b/app/server.js @@ -31,6 +31,8 @@ const config = { turnServerUrl: process.env.TURN_SERVER_URL, turnServerUsername: process.env.TURN_SERVER_USERNAME, turnServerCredential: process.env.TURN_SERVER_CREDENTIAL, + roomPasswordEnabled: process.env.ROOM_PASSWORD_ENABLED === 'true', + roomPassword: process.env.ROOM_PASSWORD || '', apiKeySecret: process.env.API_KEY_SECRET, randomImageUrl: process.env.RANDOM_IMAGE_URL || '', apiBasePath: '/api/v1', @@ -90,6 +92,10 @@ server.listen(port, () => { console.log('Server', { running_at: host, ice: config.iceServers, + room: { + password_enabled: config.roomPasswordEnabled, + password: config.roomPassword, + }, api_key_secret: config.apiKeySecret, api_docs: apiDocs, version: packageJson.version, @@ -199,6 +205,19 @@ app.get(`${config.apiBasePath}/users`, (req, res) => { return res.json({ users }); }); +// Check if Room password required +app.get('/api/roomPassword', (req, res) => { + const isPasswordRequired = config.roomPasswordEnabled; + res.json({ isPasswordRequired }); +}); + +// Check if Room password valid +app.post('/api/roomPasswordValidate', (req, res) => { + const { password } = req.body; + const success = password === config.roomPassword; + res.json({ success: success }); +}); + // Page not found app.get('*', (req, res) => { return notFound(res); diff --git a/package.json b/package.json index 54a1f97..ee3d468 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "call-me", - "version": "1.0.33", + "version": "1.0.34", "description": "Your Go-To for Instant Video Calls", "author": "Miroslav Pejic - miroslav.pejic.85@gmail.com", "license": "AGPLv3", diff --git a/public/client.js b/public/client.js index 3cb61b2..3777be6 100755 --- a/public/client.js +++ b/public/client.js @@ -40,10 +40,87 @@ document.addEventListener('DOMContentLoaded', function () { handleDirectJoin(); handleListeners(); fetchRandomImage(); + checkRoomPassword(); }); // githubDiv.style.display = 'none'; +async function checkRoomPassword(maxRetries = 3, attempts = 0) { + try { + // Fetch room configuration + const { data: config } = await axios.get('/api/roomPassword'); + + if (config.isPasswordRequired) { + // Show prompt for the password + const { value: password } = await Swal.fire({ + title: 'Room Protected', + text: 'Please enter the room password:', + input: 'password', + inputPlaceholder: 'Enter your password', + inputAttributes: { + autocapitalize: 'off', + autocorrect: 'off', + }, + showCancelButton: true, + confirmButtonText: 'Submit', + cancelButtonText: 'Cancel', + preConfirm: (password) => { + if (!password) { + Swal.showValidationMessage('Password cannot be empty'); + } + return password; + }, + }); + + // If the user cancels, exit + if (!password) { + return; + } + + // Validate the password + const { data: validationResult } = await axios.post('/api/roomPasswordValidate', { password }); + + if (validationResult.success) { + await Swal.fire({ + icon: 'success', + title: 'Access Granted', + text: 'Password validated successfully!', + timer: 1500, + showConfirmButton: false, + }); + signInPage.style.display = 'block'; + } else { + attempts++; + if (attempts < maxRetries) { + await Swal.fire({ + icon: 'error', + title: 'Invalid Password', + text: `Please try again. (${attempts}/${maxRetries} attempts)`, + }); + // Retry the process + checkRoomPassword(maxRetries, attempts); + } else { + await Swal.fire({ + icon: 'warning', + title: 'Too Many Attempts', + text: 'You have exceeded the maximum number of attempts. Please try again later.', + }); + } + } + } else { + // No password required + signInPage.style.display = 'block'; + } + } catch (error) { + console.error('Error:', error); + Swal.fire({ + icon: 'error', + title: 'Error', + text: 'An error occurred while joining the room.', + }); + } +} + // Get Random Images async function fetchRandomImage() { if (sessionStorage.cachedImage) { diff --git a/public/style.css b/public/style.css index 4561c5a..6d7cf4d 100644 --- a/public/style.css +++ b/public/style.css @@ -106,7 +106,7 @@ button { /* Home Sign in */ #signInPage { position: absolute; - display: block; + display: none; } /* General Card Styles */