Merge branch '3.2-fixes'
commit
b975b16dac
32
CHANGELOG.md
32
CHANGELOG.md
|
|
@ -1,20 +1,32 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 3.2.1
|
||||||
|
|
||||||
|
* Fix: permananent top bar by default
|
||||||
|
* Fix: `httpOnly` mode https redirect
|
||||||
|
* Add some extra checks for video stream and track
|
||||||
|
* Add Italian translation
|
||||||
|
* Add Czech translation
|
||||||
|
* Add new server option `trustProxy` for load balancing http only use case
|
||||||
|
* Add HAproxy load balance example
|
||||||
|
* Add LTI LMS integration documentation
|
||||||
|
* Fix spacing of leave button
|
||||||
|
* Fix for sharing same file multiple times
|
||||||
|
|
||||||
## 3.2
|
## 3.2
|
||||||
|
|
||||||
* Add munin plugin
|
* Add munin plugin
|
||||||
* Add muted=true search param to disble audio by deffault
|
* Add `muted=true` search param to disable audio by default
|
||||||
* Modify webtorrent tracker
|
* Modify webtorrent tracker
|
||||||
* Add key shortcut `space` for audio mute
|
* Add key shortcut `space` for audio mute
|
||||||
* Add key shortcut `v` for video mute
|
* Add key shortcut `v` for video mute
|
||||||
* Add user configurable LastN
|
* Add user configurable LastN
|
||||||
* Add option to sticky top bar (sticky by default)
|
* Add option to permananent top bar (permanent by default)
|
||||||
* update mediasoup server
|
* Update mediasoup server
|
||||||
* Add simulcast options to app config (disabled by default)
|
* Add `simulcast` options to app config (disabled by default)
|
||||||
* Add stats option to get counts of rooms and peers
|
* Add `stats` option to get counts of rooms and peers
|
||||||
* Add httpOnly option for loadbalancer backend setups
|
* Add `httpOnly` option for loadbalancer backend setups
|
||||||
* LTI integration for LMS systems like moodle
|
* LTI integration for LMS systems like moodle
|
||||||
* Add muted=false search parameter
|
|
||||||
* Add translations (12+1 languages)
|
* Add translations (12+1 languages)
|
||||||
* Add support IPv6
|
* Add support IPv6
|
||||||
* Many other fixes and refactorings
|
* Many other fixes and refactorings
|
||||||
|
|
@ -33,10 +45,10 @@
|
||||||
|
|
||||||
* Updated to mediasoup v3
|
* Updated to mediasoup v3
|
||||||
* Replace lib "passport-datporten" with "openid-client" (a general OIDC certified client)
|
* Replace lib "passport-datporten" with "openid-client" (a general OIDC certified client)
|
||||||
- OpenID Connect discovery
|
* OpenID Connect discovery
|
||||||
- Auth code flow
|
* Auth code flow
|
||||||
* Add spdy http2 support.
|
* Add spdy http2 support.
|
||||||
- Notice it does not supports node 11.x
|
* Notice it does not supports node 11.x
|
||||||
* Updated to Material UI v4
|
* Updated to Material UI v4
|
||||||
|
|
||||||
## 2.0
|
## 2.0
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,109 @@
|
||||||
|
# Howto deploy a (room based) load balanced cluster
|
||||||
|
|
||||||
|
This example will show how to setup an HA proxy to provide load balancing between several
|
||||||
|
multiparty-meeting servers.
|
||||||
|
|
||||||
|
## IP and DNS
|
||||||
|
|
||||||
|
In this basic example we use the following names and ips:
|
||||||
|
|
||||||
|
### Backend
|
||||||
|
|
||||||
|
* `mm1.example.com` <=> `192.0.2.1`
|
||||||
|
* `mm2.example.com` <=> `192.0.2.2`
|
||||||
|
* `mm3.example.com` <=> `192.0.2.3`
|
||||||
|
|
||||||
|
### Redis
|
||||||
|
|
||||||
|
* `redis.example.com` <=> `192.0.2.4`
|
||||||
|
|
||||||
|
### Load balancer HAproxy
|
||||||
|
|
||||||
|
* `meet.example.com` <=> `192.0.2.5`
|
||||||
|
|
||||||
|
## Deploy multiple multiparty-meeting servers
|
||||||
|
|
||||||
|
This is most easily done using Ansible (see below), but can be done
|
||||||
|
in any way you choose (manual, Docker, Ansible).
|
||||||
|
|
||||||
|
Read more here: [mm-ansible](https://github.com/misi/mm-ansible)
|
||||||
|
[](https://asciinema.org/a/311365)
|
||||||
|
|
||||||
|
## Setup Redis for central HTTP session store
|
||||||
|
|
||||||
|
### Use one Redis for all multiparty-meeting servers
|
||||||
|
|
||||||
|
* Deploy a Redis cluster for all instances.
|
||||||
|
* We will use in our actual example `192.0.2.4` as redis HA cluster ip. It is out of scope howto deploy it.
|
||||||
|
|
||||||
|
OR
|
||||||
|
|
||||||
|
* For testing you can use Redis from one the multiparty-meeting servers. e.g. If you plan only for testing on your first multiparty-meeting server.
|
||||||
|
* Configure Redis `redis.conf` to not only bind to your loopback but also to your global ip address too:
|
||||||
|
|
||||||
|
``` plaintext
|
||||||
|
bind 192.0.2.1
|
||||||
|
```
|
||||||
|
|
||||||
|
This example sets this to `192.0.2.1`, change this according to your local installation.
|
||||||
|
|
||||||
|
* Change your firewall config to allow incoming Redis. Example (depends on the type of firewall):
|
||||||
|
|
||||||
|
``` plaintext
|
||||||
|
chain INPUT {
|
||||||
|
policy DROP;
|
||||||
|
|
||||||
|
saddr mm2.example.com proto tcp dport 6379 ACCEPT;
|
||||||
|
saddr mm3.example.com proto tcp dport 6379 ACCEPT;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
* **Set a password, or if you don't (like in this basic example) take care to set strict firewall rules**
|
||||||
|
|
||||||
|
## Configure multiparty-meeting servers
|
||||||
|
|
||||||
|
### App config
|
||||||
|
|
||||||
|
mm/configs/app/config.js
|
||||||
|
|
||||||
|
``` js
|
||||||
|
multipartyServer : 'meet.example.com',
|
||||||
|
```
|
||||||
|
|
||||||
|
### Server config
|
||||||
|
|
||||||
|
mm/configs/server/config.js
|
||||||
|
|
||||||
|
``` js
|
||||||
|
redisOptions : { host: '192.0.2.4'},
|
||||||
|
listeningPort: 80,
|
||||||
|
httpOnly: true,
|
||||||
|
trustProxy : ['192.0.2.5'],
|
||||||
|
```
|
||||||
|
|
||||||
|
## Deploy HA proxy
|
||||||
|
|
||||||
|
* Configure cerificate / letsencrypt for `meet.example.com`
|
||||||
|
* In this example we put a complete chain and private key in /root/certificate.pem.
|
||||||
|
* Install and setup haproxy
|
||||||
|
|
||||||
|
`apt install haproxy`
|
||||||
|
|
||||||
|
* Add to /etc/haproxy/haproxy.cfg config
|
||||||
|
|
||||||
|
``` plaintext
|
||||||
|
backend multipartymeeting
|
||||||
|
balance url_param roomId
|
||||||
|
hash-type consistent
|
||||||
|
|
||||||
|
server mm1 192.0.2.1:80 check maxconn 20 verify none
|
||||||
|
server mm2 192.0.2.2:80 check maxconn 20 verify none
|
||||||
|
server mm3 192.0.2.3:80 check maxconn 20 verify none
|
||||||
|
|
||||||
|
frontend meet.example.com
|
||||||
|
bind 192.0.2.5:80
|
||||||
|
bind 192.0.2.5:443 ssl crt /root/certificate.pem
|
||||||
|
http-request redirect scheme https unless { ssl_fc }
|
||||||
|
reqadd X-Forwarded-Proto:\ https
|
||||||
|
default_backend multipartymeeting
|
||||||
|
```
|
||||||
|
|
@ -0,0 +1,61 @@
|
||||||
|
# Learning Tools Interoperability (LTI)
|
||||||
|
|
||||||
|
## LTI
|
||||||
|
|
||||||
|
Read more about IMS Global defined interface for tools like our VideoConference system integration with Learning Managment Systems(LMS) (e.g. moodle).
|
||||||
|
See: [IMS Global Learning Tool Interoperability](https://www.imsglobal.org/activity/learning-tools-interoperability)
|
||||||
|
|
||||||
|
We implemented LTI interface version 1.0/1.1
|
||||||
|
|
||||||
|
### Server config auth section LTI settings
|
||||||
|
|
||||||
|
Set in server configuration a random key and secret
|
||||||
|
|
||||||
|
``` json
|
||||||
|
auth :
|
||||||
|
{
|
||||||
|
lti :
|
||||||
|
{
|
||||||
|
consumerKey : 'key',
|
||||||
|
consumerSecret : 'secret'
|
||||||
|
},
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Configure your LMS system with secret and key settings above
|
||||||
|
|
||||||
|
#### Auth tool URL
|
||||||
|
|
||||||
|
Set tool URL to your server with path /auth/lti
|
||||||
|
|
||||||
|
``` url
|
||||||
|
https://mm.example.com/auth/lti
|
||||||
|
```
|
||||||
|
|
||||||
|
#### In moodle find external tool plugin setting and external tool action
|
||||||
|
|
||||||
|
See: [moodle external tool settings](https://docs.moodle.org/38/en/External_tool_settings)
|
||||||
|
|
||||||
|
#### Add and activity
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
#### Setup Activity
|
||||||
|
|
||||||
|
##### Activity setup basic form
|
||||||
|
|
||||||
|
Open fully the settings **Click on show more!!**
|
||||||
|

|
||||||
|
|
||||||
|
##### Empty full form
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
##### Filled out form
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## moodle plugin
|
||||||
|
|
||||||
|
Alternativly you can use multipartymeeting moodle plugin:
|
||||||
|
[https://github.com/misi/moodle-mod_multipartymeeting](https://github.com/misi/moodle-mod_multipartymeeting)
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 86 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 58 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 115 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 133 KiB |
|
|
@ -21,7 +21,6 @@ If you want the automatic approach, you can find a docker image [here](https://h
|
||||||
If you want the ansible approach, you can find ansible role [here](https://github.com/misi/mm-ansible/).
|
If you want the ansible approach, you can find ansible role [here](https://github.com/misi/mm-ansible/).
|
||||||
[](https://asciinema.org/a/311365)
|
[](https://asciinema.org/a/311365)
|
||||||
|
|
||||||
|
|
||||||
## Manual installation
|
## Manual installation
|
||||||
* Prerequisites:
|
* Prerequisites:
|
||||||
Currently multiparty-meeting will only run on nodejs v10.*
|
Currently multiparty-meeting will only run on nodejs v10.*
|
||||||
|
|
@ -106,6 +105,12 @@ $ systemctl enable multiparty-meeting
|
||||||
* 4443/tcp (default `npm start` port for developing with live browser reload, not needed in production enviroments - adjustable in app/package.json)
|
* 4443/tcp (default `npm start` port for developing with live browser reload, not needed in production enviroments - adjustable in app/package.json)
|
||||||
* 40000-49999/udp/tcp (media ports - adjustable in `server/config.js`)
|
* 40000-49999/udp/tcp (media ports - adjustable in `server/config.js`)
|
||||||
|
|
||||||
|
## Load balanced installation
|
||||||
|
To deploy this as a load balanced cluster, have a look at [HAproxy](HAproxy.md).
|
||||||
|
|
||||||
|
## Learning management integration
|
||||||
|
To integrate with an LMS (e.g. Moodle), have a look at [LTI](LTI/LTI.md).
|
||||||
|
|
||||||
## TURN configuration
|
## TURN configuration
|
||||||
|
|
||||||
* You need an addtional [TURN](https://github.com/coturn/coturn)-server for clients located behind restrictive firewalls! Add your server and credentials to `app/config.js`
|
* You need an addtional [TURN](https://github.com/coturn/coturn)-server for clients located behind restrictive firewalls! Add your server and credentials to `app/config.js`
|
||||||
|
|
|
||||||
|
|
@ -11,9 +11,10 @@
|
||||||
"@material-ui/core": "^4.5.1",
|
"@material-ui/core": "^4.5.1",
|
||||||
"@material-ui/icons": "^4.5.1",
|
"@material-ui/icons": "^4.5.1",
|
||||||
"bowser": "^2.7.0",
|
"bowser": "^2.7.0",
|
||||||
|
"create-torrent": "^4.4.1",
|
||||||
"dompurify": "^2.0.7",
|
"dompurify": "^2.0.7",
|
||||||
"domready": "^1.0.8",
|
"domready": "^1.0.8",
|
||||||
"end-of-stream": "1.4.0",
|
"end-of-stream": "1.4.1",
|
||||||
"file-saver": "^2.0.2",
|
"file-saver": "^2.0.2",
|
||||||
"hark": "^1.2.3",
|
"hark": "^1.2.3",
|
||||||
"is-electron": "^2.2.0",
|
"is-electron": "^2.2.0",
|
||||||
|
|
@ -37,7 +38,7 @@
|
||||||
"riek": "^1.1.0",
|
"riek": "^1.1.0",
|
||||||
"socket.io-client": "^2.3.0",
|
"socket.io-client": "^2.3.0",
|
||||||
"source-map-explorer": "^2.1.0",
|
"source-map-explorer": "^2.1.0",
|
||||||
"webtorrent": "^0.107.16"
|
"webtorrent": "^0.107.17"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"analyze": "source-map-explorer build/static/js/*",
|
"analyze": "source-map-explorer build/static/js/*",
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,8 @@ import * as consumerActions from './actions/consumerActions';
|
||||||
import * as producerActions from './actions/producerActions';
|
import * as producerActions from './actions/producerActions';
|
||||||
import * as notificationActions from './actions/notificationActions';
|
import * as notificationActions from './actions/notificationActions';
|
||||||
|
|
||||||
|
let createTorrent;
|
||||||
|
|
||||||
let WebTorrent;
|
let WebTorrent;
|
||||||
|
|
||||||
let saveAs;
|
let saveAs;
|
||||||
|
|
@ -704,26 +706,48 @@ export default class RoomClient
|
||||||
})
|
})
|
||||||
}));
|
}));
|
||||||
|
|
||||||
this._webTorrent.seed(
|
createTorrent(files, (err, torrent) =>
|
||||||
files,
|
{
|
||||||
{ announceList: [['wss://tracker.lab.vvc.niif.hu:443']] },
|
if (err)
|
||||||
(torrent) =>
|
|
||||||
{
|
{
|
||||||
store.dispatch(requestActions.notify(
|
return store.dispatch(requestActions.notify(
|
||||||
{
|
{
|
||||||
|
type : 'error',
|
||||||
text : intl.formatMessage({
|
text : intl.formatMessage({
|
||||||
id : 'filesharing.successfulFileShare',
|
id : 'filesharing.unableToShare',
|
||||||
defaultMessage : 'File successfully shared'
|
defaultMessage : 'Unable to share file'
|
||||||
})
|
})
|
||||||
}));
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
store.dispatch(fileActions.addFile(
|
const existingTorrent = this._webTorrent.get(torrent);
|
||||||
this._peerId,
|
|
||||||
torrent.magnetURI
|
|
||||||
));
|
|
||||||
|
|
||||||
this._sendFile(torrent.magnetURI);
|
if (existingTorrent)
|
||||||
});
|
{
|
||||||
|
return this._sendFile(existingTorrent.magnetURI);
|
||||||
|
}
|
||||||
|
|
||||||
|
this._webTorrent.seed(
|
||||||
|
files,
|
||||||
|
{ announceList: [ [ 'wss://tracker.lab.vvc.niif.hu:443' ] ] },
|
||||||
|
(newTorrent) =>
|
||||||
|
{
|
||||||
|
store.dispatch(requestActions.notify(
|
||||||
|
{
|
||||||
|
text : intl.formatMessage({
|
||||||
|
id : 'filesharing.successfulFileShare',
|
||||||
|
defaultMessage : 'File successfully shared'
|
||||||
|
})
|
||||||
|
}));
|
||||||
|
|
||||||
|
store.dispatch(fileActions.addFile(
|
||||||
|
this._peerId,
|
||||||
|
newTorrent.magnetURI
|
||||||
|
));
|
||||||
|
|
||||||
|
this._sendFile(newTorrent.magnetURI);
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// { file, name, picture }
|
// { file, name, picture }
|
||||||
|
|
@ -1081,8 +1105,8 @@ export default class RoomClient
|
||||||
logger.debug(
|
logger.debug(
|
||||||
'changeWebcam() | new selected webcam [device:%o]',
|
'changeWebcam() | new selected webcam [device:%o]',
|
||||||
device);
|
device);
|
||||||
|
if (this._webcamProducer && this._webcamProducer.track)
|
||||||
this._webcamProducer.track.stop();
|
this._webcamProducer.track.stop();
|
||||||
|
|
||||||
logger.debug('changeWebcam() | calling getUserMedia()');
|
logger.debug('changeWebcam() | calling getUserMedia()');
|
||||||
|
|
||||||
|
|
@ -1094,14 +1118,21 @@ export default class RoomClient
|
||||||
...VIDEO_CONSTRAINS[resolution]
|
...VIDEO_CONSTRAINS[resolution]
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
if (stream){
|
||||||
|
const track = stream.getVideoTracks()[0];
|
||||||
|
if (track) {
|
||||||
|
await this._webcamProducer.replaceTrack({ track });
|
||||||
|
|
||||||
const track = stream.getVideoTracks()[0];
|
store.dispatch(
|
||||||
|
producerActions.setProducerTrack(this._webcamProducer.id, track));
|
||||||
|
|
||||||
await this._webcamProducer.replaceTrack({ track });
|
} else {
|
||||||
|
logger.warn('getVideoTracks Error: First Video Track is null')
|
||||||
store.dispatch(
|
}
|
||||||
producerActions.setProducerTrack(this._webcamProducer.id, track));
|
|
||||||
|
|
||||||
|
} else {
|
||||||
|
logger.warn ('getUserMedia Error: Stream is null!')
|
||||||
|
}
|
||||||
store.dispatch(settingsActions.setSelectedWebcamDevice(deviceId));
|
store.dispatch(settingsActions.setSelectedWebcamDevice(deviceId));
|
||||||
|
|
||||||
await this._updateWebcams();
|
await this._updateWebcams();
|
||||||
|
|
@ -1337,6 +1368,13 @@ export default class RoomClient
|
||||||
|
|
||||||
async _loadDynamicImports()
|
async _loadDynamicImports()
|
||||||
{
|
{
|
||||||
|
({ default: createTorrent } = await import(
|
||||||
|
|
||||||
|
/* webpackPrefetch: true */
|
||||||
|
/* webpackChunkName: "createtorrent" */
|
||||||
|
'create-torrent'
|
||||||
|
));
|
||||||
|
|
||||||
({ default: WebTorrent } = await import(
|
({ default: WebTorrent } = await import(
|
||||||
|
|
||||||
/* webpackPrefetch: true */
|
/* webpackPrefetch: true */
|
||||||
|
|
@ -2059,6 +2097,30 @@ export default class RoomClient
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
this._torrentSupport = WebTorrent.WEBRTC_SUPPORT;
|
||||||
|
|
||||||
|
this._webTorrent = this._torrentSupport && new WebTorrent({
|
||||||
|
tracker : {
|
||||||
|
rtcConfig : {
|
||||||
|
iceServers : this._turnServers
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this._webTorrent.on('error', (error) =>
|
||||||
|
{
|
||||||
|
logger.error('Filesharing [error:"%o"]', error);
|
||||||
|
|
||||||
|
store.dispatch(requestActions.notify(
|
||||||
|
{
|
||||||
|
type : 'error',
|
||||||
|
text : intl.formatMessage({
|
||||||
|
id : 'filesharing.error',
|
||||||
|
defaultMessage : 'There was a filesharing error'
|
||||||
|
})
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
this._mediasoupDevice = new mediasoupClient.Device();
|
this._mediasoupDevice = new mediasoupClient.Device();
|
||||||
|
|
||||||
const routerRtpCapabilities =
|
const routerRtpCapabilities =
|
||||||
|
|
@ -2177,7 +2239,7 @@ export default class RoomClient
|
||||||
canShareFiles : this._torrentSupport
|
canShareFiles : this._torrentSupport
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const { peers } = await this.sendRequest(
|
const { peers, authenticated } = await this.sendRequest(
|
||||||
'join',
|
'join',
|
||||||
{
|
{
|
||||||
displayName : displayName,
|
displayName : displayName,
|
||||||
|
|
@ -2185,6 +2247,8 @@ export default class RoomClient
|
||||||
rtpCapabilities : this._mediasoupDevice.rtpCapabilities
|
rtpCapabilities : this._mediasoupDevice.rtpCapabilities
|
||||||
});
|
});
|
||||||
|
|
||||||
|
store.dispatch(meActions.loggedIn(authenticated));
|
||||||
|
|
||||||
logger.debug('_joinRoom() joined, got peers [peers:"%o"]', peers);
|
logger.debug('_joinRoom() joined, got peers [peers:"%o"]', peers);
|
||||||
|
|
||||||
for (const peer of peers)
|
for (const peer of peers)
|
||||||
|
|
|
||||||
|
|
@ -78,8 +78,8 @@ const styles = (theme) =>
|
||||||
},
|
},
|
||||||
actionButton :
|
actionButton :
|
||||||
{
|
{
|
||||||
margin : theme.spacing(1),
|
margin : theme.spacing(1, 0),
|
||||||
padding : 0
|
padding : theme.spacing(0, 1)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,8 @@ import messagesPortuguese from './translations/pt';
|
||||||
import messagesChinese from './translations/cn';
|
import messagesChinese from './translations/cn';
|
||||||
import messagesSpanish from './translations/es';
|
import messagesSpanish from './translations/es';
|
||||||
import messagesCroatian from './translations/hr';
|
import messagesCroatian from './translations/hr';
|
||||||
|
import messagesCzech from './translations/cs';
|
||||||
|
import messagesItalian from './translations/it';
|
||||||
|
|
||||||
import './index.css';
|
import './index.css';
|
||||||
|
|
||||||
|
|
@ -55,7 +57,9 @@ const messages =
|
||||||
'pt' : messagesPortuguese,
|
'pt' : messagesPortuguese,
|
||||||
'zh' : messagesChinese,
|
'zh' : messagesChinese,
|
||||||
'es' : messagesSpanish,
|
'es' : messagesSpanish,
|
||||||
'hr' : messagesCroatian
|
'hr' : messagesCroatian,
|
||||||
|
'cs' : messagesCzech,
|
||||||
|
'it' : messagesItalian
|
||||||
};
|
};
|
||||||
|
|
||||||
const locale = navigator.language.split(/[-_]/)[0]; // language without region code
|
const locale = navigator.language.split(/[-_]/)[0]; // language without region code
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,8 @@ const initialState =
|
||||||
selectedAudioDevice : null,
|
selectedAudioDevice : null,
|
||||||
advancedMode : false,
|
advancedMode : false,
|
||||||
resolution : 'medium', // low, medium, high, veryhigh, ultra
|
resolution : 'medium', // low, medium, high, veryhigh, ultra
|
||||||
lastN : 4
|
lastN : 4,
|
||||||
|
permanentTopBar : true
|
||||||
};
|
};
|
||||||
|
|
||||||
const settings = (state = initialState, action) =>
|
const settings = (state = initialState, action) =>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,136 @@
|
||||||
|
{
|
||||||
|
"socket.disconnected": "Spojení přerušeno",
|
||||||
|
"socket.reconnecting": "Spojení přerušeno, navazuji spojení..",
|
||||||
|
"socket.reconnected": "Znovu připojeno",
|
||||||
|
"socket.requestError": "Chyba při požadavku na server",
|
||||||
|
|
||||||
|
"room.chooseRoom": "Vyberte jméno místnosti, kam se chcete připojit",
|
||||||
|
"room.cookieConsent": "Tato stránka používá cookies s cílem zajistit co možná nejlepší uživatelský zážitek",
|
||||||
|
"room.joined": "Připojili jste se do místnosti",
|
||||||
|
"room.cantJoin": "Není možné se připojit do místnosti",
|
||||||
|
"room.youLocked": "Místnost byla uzamčena",
|
||||||
|
"room.cantLock": "Není možné uzamknout místnost",
|
||||||
|
"room.youUnLocked": "Místnost byla odemčena",
|
||||||
|
"room.cantUnLock": "Není možné odemknout místnost",
|
||||||
|
"room.locked": "Místnost je uzamknutá",
|
||||||
|
"room.unlocked": "Místnost je odemknutá",
|
||||||
|
"room.newLobbyPeer": "Nový účastník vstoupil do přijímací místnosti",
|
||||||
|
"room.lobbyPeerLeft": "Účastník opustil přijímací místnost",
|
||||||
|
"room.lobbyPeerChangedDisplayName": "Účastník v přijímací místnosti změnil jméno na {displayName}",
|
||||||
|
"room.lobbyPeerChangedPicture": "Účastník v přijímací místnosti změnil obrázek",
|
||||||
|
"room.setAccessCode": "Přístupový kód místnosti aktualizován",
|
||||||
|
"room.accessCodeOn": "Přístupový kód místnosti je aktivován",
|
||||||
|
"room.accessCodeOff": "Přístupový kód místnosti je deaktivován",
|
||||||
|
"room.peerChangedDisplayName": "{oldDisplayName} je nyní {displayName}",
|
||||||
|
"room.newPeer": "{displayName} se připojil do místnosti",
|
||||||
|
"room.newFile": "Je dostupný nový soubor",
|
||||||
|
"room.toggleAdvancedMode": "Přepnuto do pokročilého módu",
|
||||||
|
"room.setDemocraticView": "Rozvržení změněno na: demokratický pohled",
|
||||||
|
"room.setFilmStripView": "Rozvržení změněno na: filmový pás",
|
||||||
|
"room.loggedIn": "Jste přihlášeni",
|
||||||
|
"room.loggedOut": "Jste odhlášeni",
|
||||||
|
"room.changedDisplayName": "Vaše jméno bylo změněno na {displayName}",
|
||||||
|
"room.changeDisplayNameError": "Při změně Vašeho jména se vyskytla chyba",
|
||||||
|
"room.chatError": "Zprávu nebylo možné odeslat",
|
||||||
|
"room.aboutToJoin": "Připojujete se ke konferenci",
|
||||||
|
"room.roomId": "ID místnosti: {roomName}",
|
||||||
|
"room.setYourName": "Zadejte své jméno a vyberte, jak se chcete připojit:",
|
||||||
|
"room.audioOnly": "Pouze Audio",
|
||||||
|
"room.audioVideo": "Audio a Video",
|
||||||
|
"room.youAreReady": "Ok, jste připraven",
|
||||||
|
"room.emptyRequireLogin": "Místnost je prázdná! Pro spuštění konference se přihlašte nebo počkejte, než se připojí hostitel",
|
||||||
|
"room.locketWait": "Místnost je uzamčena - vydržte, než vás někdo pustí dovnitř ...",
|
||||||
|
"room.lobbyAdministration": "Administrace Přijímací místnosti",
|
||||||
|
"room.peersInLobby": "Účastníci v Přijímací místnosti",
|
||||||
|
"room.lobbyEmpty": "V Přijímací místnosti v současné době nikdo není",
|
||||||
|
"room.hiddenPeers": "{hiddenPeersCount, plural, one {účastník} other {účastníci}}",
|
||||||
|
"room.me": "Já",
|
||||||
|
"room.spotlights": "Aktivní Účastníci",
|
||||||
|
"room.passive": "Pasivní Účastníci",
|
||||||
|
"room.videoPaused": "Toto video bylo pozastaveno",
|
||||||
|
|
||||||
|
"tooltip.login": "Přihlášení",
|
||||||
|
"tooltip.logout": "Odhlášení",
|
||||||
|
"tooltip.admitFromLobby": "Povolit uživatele z Přijímací místnosti",
|
||||||
|
"tooltip.lockRoom": "Uzamknout místnost",
|
||||||
|
"tooltip.unLockRoom": "Odemknout místnost",
|
||||||
|
"tooltip.enterFullscreen": "Zapnout režim celé obrazovky (fullscreen)",
|
||||||
|
"tooltip.leaveFullscreen": "Vypnout režim celé obrazovky (fullscreen)",
|
||||||
|
"tooltip.lobby": "Ukázat Přijímací místnost",
|
||||||
|
"tooltip.settings": "Zobrazit nastavení",
|
||||||
|
|
||||||
|
"label.roomName": "Jméno místnosti",
|
||||||
|
"label.chooseRoomButton": "Pokračovat",
|
||||||
|
"label.yourName": "Vaše jméno",
|
||||||
|
"label.newWindow": "Nové okno",
|
||||||
|
"label.fullscreen": "Režim celé obrazovky (Fullscreen)",
|
||||||
|
"label.openDrawer": "Otevřít zásuvku",
|
||||||
|
"label.leave": "Opustit",
|
||||||
|
"label.chatInput": "Napište zprávu chatu...",
|
||||||
|
"label.chat": "Chat",
|
||||||
|
"label.filesharing": "Sdílení souborů",
|
||||||
|
"label.participants": "Účastníci",
|
||||||
|
"label.shareFile": "Sdílet soubor",
|
||||||
|
"label.fileSharingUnsupported": "Sdílení souborů není podporováno",
|
||||||
|
"label.unknown": "Neznámý",
|
||||||
|
"label.democratic": "Rozvržení: Demokratické",
|
||||||
|
"label.filmstrip": "Rozvržení: Filmový pás",
|
||||||
|
"label.low": "Nízké",
|
||||||
|
"label.medium": "Střední",
|
||||||
|
"label.high": "Vysoké (HD)",
|
||||||
|
"label.veryHigh": "Velmi vysoké (FHD)",
|
||||||
|
"label.ultra": "Ultra (UHD)",
|
||||||
|
"label.close": "Zavřít",
|
||||||
|
|
||||||
|
"settings.settings": "Nastavení",
|
||||||
|
"settings.camera": "Kamera",
|
||||||
|
"settings.selectCamera": "Vyberte video zařízení",
|
||||||
|
"settings.cantSelectCamera": "Není možné vybrat video zařízení",
|
||||||
|
"settings.audio": "Audio zařízení",
|
||||||
|
"settings.selectAudio": "Vyberte audio zařízení",
|
||||||
|
"settings.cantSelectAudio": "Není možno vybrat audio zařízení",
|
||||||
|
"settings.resolution": "Vyberte rozlišení vašeho videa",
|
||||||
|
"settings.layout": "Rozvržení místnosti",
|
||||||
|
"settings.selectRoomLayout": "Vyberte rozvržení místnosti",
|
||||||
|
"settings.advancedMode": "Pokočilý mód",
|
||||||
|
|
||||||
|
"filesharing.saveFileError": "Není možné uložit soubor",
|
||||||
|
"filesharing.startingFileShare": "Pokouším se sdílet soubor",
|
||||||
|
"filesharing.successfulFileShare": "Soubor byl úspěšně sdílen",
|
||||||
|
"filesharing.unableToShare": "Není možné sdílet soubor",
|
||||||
|
"filesharing.error": "Při sdílení souboru se vyskytla chyba",
|
||||||
|
"filesharing.finished": "Stahování souboru dokončeno",
|
||||||
|
"filesharing.save": "Uložit",
|
||||||
|
"filesharing.sharedFile": "{displayName} sdílel(a) soubor",
|
||||||
|
"filesharing.download": "Stáhnout",
|
||||||
|
"filesharing.missingSeeds": "Pokud tento proces trvá dlouho, nikdo zřejmě neseeduje tento torrent. Pokuste se někoho požádat, aby znovu nahrál soubor, který potřebujete.",
|
||||||
|
|
||||||
|
"devices.devicesChanged": "Vaše zařízení se změnila, nastavte je v dialogu nastavení",
|
||||||
|
|
||||||
|
"device.audioUnsupported": "Audio není podporováno",
|
||||||
|
"device.activateAudio": "Aktivovat audio",
|
||||||
|
"device.muteAudio": "Ztišit zvuk",
|
||||||
|
"device.unMuteAudio": "Zrušit ztišení zvuku",
|
||||||
|
|
||||||
|
"device.videoUnsupported": "Video není podporováno",
|
||||||
|
"device.startVideo": "Spustit video",
|
||||||
|
"device.stopVideo": "Zastavit video",
|
||||||
|
|
||||||
|
"device.screenSharingUnsupported": "Sdílení obrazovky není podporováno",
|
||||||
|
"device.startScreenSharing": "Spustit sdílení obrazovky",
|
||||||
|
"device.stopScreenSharing": "Zastavit sdílení obrazovky",
|
||||||
|
|
||||||
|
"devices.microphoneDisconnected": "Mikrofon odpojen",
|
||||||
|
"devices.microphoneError": "Při přístupu k vašemu mikrofonu se vyskytla chyba",
|
||||||
|
"devices.microPhoneMute": "Mikrofon ztišen",
|
||||||
|
"devices.micophoneUnMute": "Ztišení mikrofonu zrušeno",
|
||||||
|
"devices.microphoneEnable": "Mikrofon povolen",
|
||||||
|
"devices.microphoneMuteError": "Není možné ztišit váš mikrofon",
|
||||||
|
"devices.microphoneUnMuteError": "Není možné zrušit ztišení vašeho mikrofonu",
|
||||||
|
|
||||||
|
"devices.screenSharingDisconnected" : "Sdílení obrazovky odpojeno",
|
||||||
|
"devices.screenSharingError": "Při přístupu k vaší obrazovce se vyskytla chyba",
|
||||||
|
|
||||||
|
"devices.cameraDisconnected": "Kamera odpojena",
|
||||||
|
"devices.cameraError": "Při přístupu k vaší kameře se vyskytla chyba"
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,140 @@
|
||||||
|
{
|
||||||
|
"socket.disconnected": "Sei stato disconnesso",
|
||||||
|
"socket.reconnecting": "Sei stato disconnesso, stiamo provando a riconnetterti",
|
||||||
|
"socket.reconnected": "Sei stato riconnesso",
|
||||||
|
"socket.requestError": "Errore di richiesta al server",
|
||||||
|
|
||||||
|
"room.chooseRoom": "Scegli il nome della stanza in cui vorresti entrare",
|
||||||
|
"room.cookieConsent": "Questo sito fa uso di cookies per migliorare l'esperienza utente",
|
||||||
|
"room.consentUnderstand": "Ho capito",
|
||||||
|
"room.joined": "Sei entrato nella stanza",
|
||||||
|
"room.cantJoin": "Impossibile entrare nella stanza",
|
||||||
|
"room.youLocked": "Hai bloccato la stanza",
|
||||||
|
"room.cantLock": "Impossibile bloccare la stanza",
|
||||||
|
"room.youUnLocked": "Hai sbloccato la stanza",
|
||||||
|
"room.cantUnLock": "Impossibile sbloccare la stanza",
|
||||||
|
"room.locked": "La stanza è ora bloccata",
|
||||||
|
"room.unlocked": "La stanza è ora sbloccata",
|
||||||
|
"room.newLobbyPeer": "Un nuovo partecipante è entrato nella lobby",
|
||||||
|
"room.lobbyPeerLeft": "Un partecipante ha abbandonato la lobby",
|
||||||
|
"room.lobbyPeerChangedDisplayName": "Un partecipante della lobby ha cambiato nome in {displayName}",
|
||||||
|
"room.lobbyPeerChangedPicture": "Un partecipante della lobby ha cambiato immagine del profilo",
|
||||||
|
"room.setAccessCode": "Codice d'accesso della stanza aggiornato",
|
||||||
|
"room.accessCodeOn": "Il codice d'accesso della stanza è attivato",
|
||||||
|
"room.accessCodeOff": "Il codice d'accesso della stanza è disattivato",
|
||||||
|
"room.peerChangedDisplayName": "{oldDisplayName} ora si chiama {displayName}",
|
||||||
|
"room.newPeer": "{displayName} è entrato nella stanza",
|
||||||
|
"room.newFile": "Nuovo file disponibile",
|
||||||
|
"room.toggleAdvancedMode": "Attivata/disattivata modalità avanzata",
|
||||||
|
"room.setDemocraticView": "Aspetto cambiato in vista democratica",
|
||||||
|
"room.setFilmStripView": "Aspetto cambiato in vista filmstrip",
|
||||||
|
"room.loggedIn": "Hai eseguito il log in",
|
||||||
|
"room.loggedOut": "Hai eseguito il log out",
|
||||||
|
"room.changedDisplayName": "Il tuo nome visualizzato è cambiato in{displayName}",
|
||||||
|
"room.changeDisplayNameError": "Errore nel modificare il tuo nome visualizzato",
|
||||||
|
"room.chatError": "Impossibile mandare messaggio in chat",
|
||||||
|
"room.aboutToJoin": "Stai per entrare in un meeting",
|
||||||
|
"room.roomId": "ID stanza: {roomName}",
|
||||||
|
"room.setYourName": "Imposta il tuo nome per la partecipazione, e scegli in che modo vuoi entrare:",
|
||||||
|
"room.audioOnly": "Solo Audio",
|
||||||
|
"room.audioVideo": "Audio e Video",
|
||||||
|
"room.youAreReady": "Ok, sei pronto",
|
||||||
|
"room.emptyRequireLogin": "La stanza è vuota! Puoi fare il log in per iniziare il meeting, o aspettare finchè l'host non entra",
|
||||||
|
"room.locketWait": "La stanza è bloccata - resta in attesa finchè qualcuno non ti fa entrare...",
|
||||||
|
"room.lobbyAdministration": "Amministrazione lobby",
|
||||||
|
"room.peersInLobby": "Participanti della lobby",
|
||||||
|
"room.lobbyEmpty": "Attualmente non c'è nessuno nella lobby",
|
||||||
|
"room.hiddenPeers": "{hiddenPeersCount, plural, one {participant} other {participants}}",
|
||||||
|
"room.me": "Io",
|
||||||
|
"room.spotlights": "Partecipanti in Evidenza",
|
||||||
|
"room.passive": "Participanti Passivi",
|
||||||
|
"room.videoPaused": "Il video è in pausa",
|
||||||
|
|
||||||
|
"tooltip.login": "Log in",
|
||||||
|
"tooltip.logout": "Log out",
|
||||||
|
"tooltip.admitFromLobby": "Ammetti dalla lobby",
|
||||||
|
"tooltip.lockRoom": "Blocca stanza",
|
||||||
|
"tooltip.unLockRoom": "Sblocca stanza",
|
||||||
|
"tooltip.enterFullscreen": "Modalità schermo intero",
|
||||||
|
"tooltip.leaveFullscreen": "Esci dalla modalità schermo intero",
|
||||||
|
"tooltip.lobby": "Mostra lobby",
|
||||||
|
"tooltip.settings": "Mostra impostazioni",
|
||||||
|
"tooltip.participants": "Mostra partecipanti",
|
||||||
|
|
||||||
|
"label.roomName": "Nome della stanza",
|
||||||
|
"label.chooseRoomButton": "Continua",
|
||||||
|
"label.yourName": "Il tuo nome",
|
||||||
|
"label.newWindow": "Nuova finestra",
|
||||||
|
"label.fullscreen": "Schermo intero",
|
||||||
|
"label.openDrawer": "Apri cassetto",
|
||||||
|
"label.leave": "Esci",
|
||||||
|
"label.chatInput": "Inserire messaggio...",
|
||||||
|
"label.chat": "Chat",
|
||||||
|
"label.filesharing": "Condivisione file",
|
||||||
|
"label.participants": "Partecipanti",
|
||||||
|
"label.shareFile": "Condividi file",
|
||||||
|
"label.fileSharingUnsupported": "Condivisione file non supportata",
|
||||||
|
"label.unknown": "Sconosciuto",
|
||||||
|
"label.democratic": "Vista Democratica",
|
||||||
|
"label.filmstrip": "Vista Filmstrip",
|
||||||
|
"label.low": "Bassa",
|
||||||
|
"label.medium": "Media",
|
||||||
|
"label.high": "Alta (HD)",
|
||||||
|
"label.veryHigh": "Molto alta (FHD)",
|
||||||
|
"label.ultra": "Ultra (UHD)",
|
||||||
|
"label.close": "Chiudi",
|
||||||
|
|
||||||
|
"settings.settings": "Impostazioni",
|
||||||
|
"settings.camera": "Videocamera",
|
||||||
|
"settings.selectCamera": "Seleziona dispositivo video",
|
||||||
|
"settings.cantSelectCamera": "Impossibile selezionare dispositivo video",
|
||||||
|
"settings.audio": "Dispositivo audio",
|
||||||
|
"settings.selectAudio": "Seleziona dispositivo audio",
|
||||||
|
"settings.cantSelectAudio": "Impossibile selezionare dispositivo audio",
|
||||||
|
"settings.resolution": "Seleziona risoluzione",
|
||||||
|
"settings.layout": "Aspetto stanza",
|
||||||
|
"settings.selectRoomLayout": "Seleziona aspetto stanza",
|
||||||
|
"settings.advancedMode": "Modalità avanzata",
|
||||||
|
"settings.permanentTopBar": "Barra superiore permanente",
|
||||||
|
"settings.lastn": "Numero di video visibili",
|
||||||
|
|
||||||
|
"filesharing.saveFileError": "Impossibile salvare file",
|
||||||
|
"filesharing.startingFileShare": "Tentativo di condivisione file",
|
||||||
|
"filesharing.successfulFileShare": "File condiviso con successo",
|
||||||
|
"filesharing.unableToShare": "Impossibile condividere file",
|
||||||
|
"filesharing.error": "Errore generico nella condivisione file",
|
||||||
|
"filesharing.finished": "Il file è stato scaricato",
|
||||||
|
"filesharing.save": "Salva",
|
||||||
|
"filesharing.sharedFile": "{displayName} ha condiviso un file",
|
||||||
|
"filesharing.download": "Download",
|
||||||
|
"filesharing.missingSeeds": "Se questo processo impiega troppo tempo, questo torrent potrebbe non avere alcun seed. Prova a chiedere a qualcuno di caricare nuovamente il file che desideri.",
|
||||||
|
|
||||||
|
"devices.devicesChanged": "Il tuo dispositivo è cambiato, configura i dispositivi nel menù di impostazioni",
|
||||||
|
|
||||||
|
"device.audioUnsupported": "Dispositivo audio non supportato",
|
||||||
|
"device.activateAudio": "Attiva audio",
|
||||||
|
"device.muteAudio": "Silenzia audio",
|
||||||
|
"device.unMuteAudio": "Riattiva audio",
|
||||||
|
|
||||||
|
"device.videoUnsupported": "Dispositivo video non supportato",
|
||||||
|
"device.startVideo": "Attiva video",
|
||||||
|
"device.stopVideo": "Disattiva video",
|
||||||
|
|
||||||
|
"device.screenSharingUnsupported": "Condivisione Schermo non supportata",
|
||||||
|
"device.startScreenSharing": "Inizia Condivisione Schermo",
|
||||||
|
"device.stopScreenSharing": "Termina Condivisione Schermo",
|
||||||
|
|
||||||
|
"devices.microphoneDisconnected": "Microfono scollegato",
|
||||||
|
"devices.microphoneError": "Errore con l'accesso al microfono",
|
||||||
|
"devices.microPhoneMute": "Microfono silenziato",
|
||||||
|
"devices.micophoneUnMute": "Microfono riattivato",
|
||||||
|
"devices.microphoneEnable": "Microfono attivo",
|
||||||
|
"devices.microphoneMuteError": "Impossibile silenziare il microfono",
|
||||||
|
"devices.microphoneUnMuteError": "Impossibile riattivare il microfono",
|
||||||
|
|
||||||
|
"devices.screenSharingDisconnected" : "Disconnesso da Condivisione Schermo",
|
||||||
|
"devices.screenSharingError": "Errore con l'accesso al tuo schermo",
|
||||||
|
|
||||||
|
"devices.cameraDisconnected": "Videocamera scollegata",
|
||||||
|
"devices.cameraError": "Errore con l'accesso alla videocamera"
|
||||||
|
}
|
||||||
|
|
@ -50,6 +50,12 @@ module.exports =
|
||||||
// listeningRedirectPort disabled
|
// listeningRedirectPort disabled
|
||||||
// use case: loadbalancer backend
|
// use case: loadbalancer backend
|
||||||
httpOnly : false,
|
httpOnly : false,
|
||||||
|
// WebServer/Express trust proxy config for httpOnly mode
|
||||||
|
// You can find more info:
|
||||||
|
// - https://expressjs.com/en/guide/behind-proxies.html
|
||||||
|
// - https://www.npmjs.com/package/proxy-addr
|
||||||
|
// use case: loadbalancer backend
|
||||||
|
trustProxy : '',
|
||||||
// If this is set to true, only signed-in users will be able
|
// If this is set to true, only signed-in users will be able
|
||||||
// to join a room directly. Non-signed-in users (guests) will
|
// to join a room directly. Non-signed-in users (guests) will
|
||||||
// always be put in the lobby regardless of room lock status.
|
// always be put in the lobby regardless of room lock status.
|
||||||
|
|
|
||||||
|
|
@ -472,7 +472,7 @@ class Room extends EventEmitter
|
||||||
.filter((joinedPeer) => joinedPeer.id !== peer.id)
|
.filter((joinedPeer) => joinedPeer.id !== peer.id)
|
||||||
.map((joinedPeer) => (joinedPeer.peerInfo));
|
.map((joinedPeer) => (joinedPeer.peerInfo));
|
||||||
|
|
||||||
cb(null, { peers: peerInfos });
|
cb(null, { peers: peerInfos, authenticated: peer.authenticated });
|
||||||
|
|
||||||
// Mark the new Peer as joined.
|
// Mark the new Peer as joined.
|
||||||
peer.joined = true;
|
peer.joined = true;
|
||||||
|
|
|
||||||
|
|
@ -99,6 +99,10 @@ const session = expressSession({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (config.trustProxy) {
|
||||||
|
app.set('trust proxy', config.trustProxy);
|
||||||
|
}
|
||||||
|
|
||||||
app.use(session);
|
app.use(session);
|
||||||
|
|
||||||
passport.serializeUser((user, done) =>
|
passport.serializeUser((user, done) =>
|
||||||
|
|
@ -167,7 +171,7 @@ function setupLTI(ltiConfig)
|
||||||
|
|
||||||
const ltiStrategy = new LTIStrategy(
|
const ltiStrategy = new LTIStrategy(
|
||||||
ltiConfig,
|
ltiConfig,
|
||||||
function(req, lti, done)
|
(req, lti, done) =>
|
||||||
{
|
{
|
||||||
// LTI launch parameters
|
// LTI launch parameters
|
||||||
if (lti)
|
if (lti)
|
||||||
|
|
@ -332,7 +336,7 @@ async function setupAuth()
|
||||||
// lti launch
|
// lti launch
|
||||||
app.post('/auth/lti',
|
app.post('/auth/lti',
|
||||||
passport.authenticate('lti', { failureRedirect: '/' }),
|
passport.authenticate('lti', { failureRedirect: '/' }),
|
||||||
function(req, res)
|
(req, res) =>
|
||||||
{
|
{
|
||||||
res.redirect(`/${req.user.room}`);
|
res.redirect(`/${req.user.room}`);
|
||||||
}
|
}
|
||||||
|
|
@ -342,7 +346,7 @@ async function setupAuth()
|
||||||
app.get('/auth/logout', (req, res) =>
|
app.get('/auth/logout', (req, res) =>
|
||||||
{
|
{
|
||||||
req.logout();
|
req.logout();
|
||||||
res.send(logoutHelper());
|
req.session.destroy(() => res.send(logoutHelper()));
|
||||||
});
|
});
|
||||||
|
|
||||||
// callback
|
// callback
|
||||||
|
|
@ -391,7 +395,7 @@ async function runHttpsServer()
|
||||||
|
|
||||||
app.all('*', async (req, res, next) =>
|
app.all('*', async (req, res, next) =>
|
||||||
{
|
{
|
||||||
if (req.secure)
|
if (req.secure || config.httpOnly )
|
||||||
{
|
{
|
||||||
const ltiURL = new URL(`${req.protocol }://${ req.get('host') }${req.originalUrl}`);
|
const ltiURL = new URL(`${req.protocol }://${ req.get('host') }${req.originalUrl}`);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue