[mirotalksfu] - add host protection
هذا الالتزام موجود في:
@@ -30,6 +30,13 @@ const io = require('socket.io')(httpsServer);
|
||||
const host = 'https://' + 'localhost' + ':' + config.listenPort; // config.listenIp
|
||||
const announcedIP = config.mediasoup.webRtcTransport.listenIps[0].announcedIp;
|
||||
|
||||
const hostCfg = {
|
||||
protected: config.hostProtected,
|
||||
username: config.hostUsername,
|
||||
password: config.hostPassword,
|
||||
authenticated: false,
|
||||
};
|
||||
|
||||
const apiBasePath = '/api/v1'; // api endpoint path
|
||||
const api_docs = host + apiBasePath + '/docs'; // api docs
|
||||
|
||||
@@ -64,7 +71,24 @@ app.use((err, req, res, next) => {
|
||||
|
||||
// all start from here
|
||||
app.get(['/'], (req, res) => {
|
||||
res.sendFile(path.join(__dirname, '../../', 'public/view/landing.html'));
|
||||
if (hostCfg.protected == true) {
|
||||
res.sendFile(path.join(__dirname, '../../', 'public/view/login.html'));
|
||||
} else {
|
||||
res.sendFile(path.join(__dirname, '../../', 'public/view/landing.html'));
|
||||
}
|
||||
});
|
||||
|
||||
// handle login on host protected
|
||||
app.get(['/login'], (req, res) => {
|
||||
let ip = req.headers['x-forwarded-for'] || req.socket.remoteAddress;
|
||||
log.debug(`request login to host from: ${ip}`, req.query);
|
||||
if (req.query.username == hostCfg.username && req.query.password == hostCfg.password) {
|
||||
hostCfg.authenticated = true;
|
||||
res.sendFile(path.join(__dirname, '../../', 'public/view/landing.html'));
|
||||
} else {
|
||||
hostCfg.authenticated = false;
|
||||
res.sendFile(path.join(__dirname, '../../', 'public/view/login.html'));
|
||||
}
|
||||
});
|
||||
|
||||
// set new room name and join
|
||||
@@ -89,11 +113,15 @@ app.get('/join/', (req, res) => {
|
||||
|
||||
// join to room
|
||||
app.get('/join/*', (req, res) => {
|
||||
if (Object.keys(req.query).length > 0) {
|
||||
log.debug('redirect:' + req.url + ' to ' + url.parse(req.url).pathname);
|
||||
res.redirect(url.parse(req.url).pathname);
|
||||
if (hostCfg.authenticated) {
|
||||
if (Object.keys(req.query).length > 0) {
|
||||
log.debug('redirect:' + req.url + ' to ' + url.parse(req.url).pathname);
|
||||
res.redirect(url.parse(req.url).pathname);
|
||||
} else {
|
||||
res.sendFile(path.join(__dirname, '../../', 'public/view/Room.html'));
|
||||
}
|
||||
} else {
|
||||
res.sendFile(path.join(__dirname, '../../', 'public/view/Room.html'));
|
||||
res.sendFile(path.join(__dirname, '../../', 'public/view/login.html'));
|
||||
}
|
||||
});
|
||||
|
||||
@@ -151,6 +179,7 @@ async function ngrokStart() {
|
||||
let pu1 = data.tunnels[1].public_url;
|
||||
let tunnel = pu0.startsWith('https') ? pu0 : pu1;
|
||||
log.debug('Listening on', {
|
||||
hostConfig: hostCfg,
|
||||
announced_ip: announcedIP,
|
||||
server: host,
|
||||
tunnel: tunnel,
|
||||
@@ -187,6 +216,7 @@ httpsServer.listen(config.listenPort, () => {
|
||||
return;
|
||||
}
|
||||
log.debug('Listening on', {
|
||||
hostConfig: hostCfg,
|
||||
announced_ip: announcedIP,
|
||||
server: host,
|
||||
api_docs: api_docs,
|
||||
|
||||
@@ -22,6 +22,15 @@ const getLocalIp = () => {
|
||||
// https://api.ipify.org
|
||||
|
||||
module.exports = {
|
||||
/*
|
||||
Host Protection (default False)
|
||||
In order to protect your host set
|
||||
hostProtected to true and set your own Username and Password
|
||||
*/
|
||||
hostProtected: false,
|
||||
hostUsername: 'username',
|
||||
hostPassword: 'password',
|
||||
// app listen on
|
||||
listenIp: '0.0.0.0',
|
||||
listenPort: 3010,
|
||||
// ssl/README.md
|
||||
|
||||
202
public/view/login.html
Normal file
202
public/view/login.html
Normal file
@@ -0,0 +1,202 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" class="no-js">
|
||||
<head>
|
||||
<!-- Global site tag (gtag.js) - Google Analytics -->
|
||||
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=G-ZRF9TVSZ0J"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag() {
|
||||
dataLayer.push(arguments);
|
||||
}
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', 'G-ZRF9TVSZ0J');
|
||||
</script>
|
||||
|
||||
<!-- Title and Icon -->
|
||||
|
||||
<title>MiroTalk SFU - Host Protected login required.</title>
|
||||
<link rel="shortcut icon" href="../images/logo.svg" />
|
||||
<link rel="apple-touch-icon" href="../images/logo.svg" />
|
||||
|
||||
<!-- Meta Information -->
|
||||
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
|
||||
<meta
|
||||
name="description"
|
||||
content="MiroTalk SFU powered by WebRTC and mediasoup, Real-time secure video calls, messaging and screen sharing capabilities in the browser."
|
||||
/>
|
||||
<meta
|
||||
name="keywords"
|
||||
content="webrtc, mediasoup, mediasoup-client, self hosted, voip, sip, real-time communications, chat, messaging, meet, webrtc stun, webrtc turn, video meeting, video chat, video conference, multi video chat, multi video conference, peer to peer, p2p, rtc, alternative to, zoom, microsoft teams, google meet, jitsi, meeting"
|
||||
/>
|
||||
|
||||
<!-- https://ogp.me -->
|
||||
|
||||
<meta property="og:type" content="app-webrtc" />
|
||||
<meta property="og:site_name" content="MiroTalk SFU" />
|
||||
<meta property="og:title" content="Click the link to make a call." />
|
||||
<meta
|
||||
property="og:description"
|
||||
content="MiroTalk SFU calling provides real-time video calls, messaging and screen sharing."
|
||||
/>
|
||||
<meta property="og:image" content="https://sfu.mirotalk.org/images/mirotalksfu.png" />
|
||||
|
||||
<!-- StyleSheet -->
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=IBM+Plex+Sans:400,600" />
|
||||
<link rel="stylesheet" href="../css/landing.css" />
|
||||
|
||||
<!-- Js scripts -->
|
||||
|
||||
<script src="https://unpkg.com/animejs@3.0.1/lib/anime.min.js"></script>
|
||||
<script src="https://unpkg.com/scrollreveal@4.0.0/dist/scrollreveal.min.js"></script>
|
||||
</head>
|
||||
<body class="is-boxed has-animations">
|
||||
<div class="body-wrap">
|
||||
<header class="site-header">
|
||||
<div class="container">
|
||||
<div class="site-header-inner">
|
||||
<div class="brand header-brand">
|
||||
<h1 class="m-0">
|
||||
<a href="/">
|
||||
<img class="header-logo-image" src="../images/logo.svg" alt="Logo" />
|
||||
</a>
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main>
|
||||
<section class="hero">
|
||||
<div class="container">
|
||||
<div class="hero-inner">
|
||||
<div class="hero-copy">
|
||||
<fieldset>
|
||||
<br />
|
||||
<div class="mb-12">
|
||||
<input
|
||||
id="username"
|
||||
class="form-input"
|
||||
type="name"
|
||||
placeholder="Username"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<br />
|
||||
<div class="mb-12">
|
||||
<input
|
||||
id="password"
|
||||
class="form-input"
|
||||
type="password"
|
||||
placeholder="Password"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div class="mt-24 mb-32">
|
||||
<button id="loginButton" class="button button-primary button-block">
|
||||
Login
|
||||
</button>
|
||||
</div>
|
||||
</fieldset>
|
||||
<script>
|
||||
let loginBtn = document.getElementById('loginButton');
|
||||
|
||||
loginBtn.onclick = (e) => {
|
||||
let username = document.getElementById('username').value;
|
||||
let password = document.getElementById('password').value;
|
||||
if (username && password) {
|
||||
window.location.href = `/login?username=${username}&password=${password}`;
|
||||
return;
|
||||
}
|
||||
alert('Username and Password required');
|
||||
};
|
||||
</script>
|
||||
</div>
|
||||
<div class="hero-figure anime-element">
|
||||
<svg class="placeholder" width="528" height="396" viewBox="0 0 528 396">
|
||||
<rect width="528" height="396" style="fill: transparent" />
|
||||
</svg>
|
||||
<div class="hero-figure-box hero-figure-box-01" data-rotation="45deg"></div>
|
||||
<div class="hero-figure-box hero-figure-box-02" data-rotation="-45deg"></div>
|
||||
<div class="hero-figure-box hero-figure-box-03" data-rotation="0deg"></div>
|
||||
<div class="hero-figure-box hero-figure-box-04" data-rotation="-135deg"></div>
|
||||
<div class="hero-figure-box hero-figure-box-05"></div>
|
||||
<div class="hero-figure-box hero-figure-box-06"></div>
|
||||
<div class="hero-figure-box hero-figure-box-07"></div>
|
||||
<div class="hero-figure-box hero-figure-box-08" data-rotation="-22deg"></div>
|
||||
<div class="hero-figure-box hero-figure-box-09" data-rotation="-52deg"></div>
|
||||
<div class="hero-figure-box hero-figure-box-10" data-rotation="-50deg"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<footer class="site-footer">
|
||||
<div class="container">
|
||||
<div class="site-footer-inner">
|
||||
<div class="brand footer-brand">
|
||||
<a href="/">
|
||||
<img class="header-logo-image" src="../images/logo.svg" alt="Logo" />
|
||||
</a>
|
||||
</div>
|
||||
<ul class="footer-links list-reset">
|
||||
<li>
|
||||
<a href="/privacy">Privacy Policy</a>
|
||||
</li>
|
||||
<li>
|
||||
Contact:
|
||||
<a target="_blank" href="https://www.linkedin.com/in/miroslav-pejic-976a07101/"
|
||||
>Miroslav Pejic</a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="footer-social-links list-reset">
|
||||
<li>
|
||||
<a target="_blank" href="https://github.com/miroslavpejic85/mirotalksfu">
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
|
||||
<title>GitHub</title>
|
||||
<path
|
||||
d="M7.95 0C3.578 0 0 3.578 0 7.95c0 3.479 2.286 6.46 5.466 7.553.397.1.497-.199.497-.397v-1.392c-2.187.497-2.683-.994-2.683-.994-.398-.894-.895-1.192-.895-1.192-.696-.497.1-.497.1-.497.795.1 1.192.795 1.192.795.696 1.292 1.888.894 2.286.696.1-.497.298-.895.497-1.093-1.79-.2-3.578-.895-3.578-3.976 0-.894.298-1.59.795-2.087-.1-.198-.397-.993.1-2.086 0 0 .695-.2 2.186.795a6.408 6.408 0 0 1 1.987-.299c.696 0 1.392.1 1.988.299 1.49-.994 2.186-.795 2.186-.795.398 1.093.199 1.888.1 2.086.496.597.795 1.292.795 2.087 0 3.081-1.889 3.677-3.677 3.876.298.398.596.895.596 1.59v2.187c0 .198.1.496.596.397C13.714 14.41 16 11.43 16 7.95 15.9 3.578 12.323 0 7.95 0z"
|
||||
fill="#0270D7"
|
||||
/>
|
||||
</svg>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a target="_blank" href="https://www.facebook.com/mirotalk">
|
||||
<span class="screen-reader-text">Facebook</span>
|
||||
<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M6.023 16L6 9H3V6h3V4c0-2.7 1.672-4 4.08-4 1.153 0 2.144.086 2.433.124v2.821h-1.67c-1.31 0-1.563.623-1.563 1.536V6H13l-1 3H9.28v7H6.023z"
|
||||
fill="#0270D7"
|
||||
/>
|
||||
</svg>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a target="_blank" href="mailto:miroslav.pejic.85@gmail.com">
|
||||
<span class="screen-reader-text">Google</span>
|
||||
<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M7.9 7v2.4H12c-.2 1-1.2 3-4 3-2.4 0-4.3-2-4.3-4.4 0-2.4 2-4.4 4.3-4.4 1.4 0 2.3.6 2.8 1.1l1.9-1.8C11.5 1.7 9.9 1 8 1 4.1 1 1 4.1 1 8s3.1 7 7 7c4 0 6.7-2.8 6.7-6.8 0-.5 0-.8-.1-1.2H7.9z"
|
||||
fill="#0270D7"
|
||||
/>
|
||||
</svg>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="footer-copyright">© 2021 MiroTalk SFU, all rights reserved</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
<script src="../js/landing.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
المرجع في مشكلة جديدة
حظر مستخدم