Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/spreed.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoas Schilling <coding@schilljs.com>2017-10-11 18:23:32 +0300
committerJoachim Bauch <bauch@struktur.de>2017-11-02 13:23:51 +0300
commitf7f9e7929c7c277a388b4ca358b3ef6bbed172f1 (patch)
tree3f491143205d97af7453ece5698e7edf2727f293
parentfaf4e9c43ce6a3dc1ca720b667af5e41c7340447 (diff)
Allow multiple signaling servers
Signed-off-by: Joas Schilling <coding@schilljs.com>
-rw-r--r--css/settings-admin.scss1
-rw-r--r--js/admin/signaling-server.js136
-rw-r--r--lib/BackendNotifier.php11
-rw-r--r--lib/Config.php43
-rw-r--r--lib/Controller/PageController.php8
-rw-r--r--lib/Controller/SignalingController.php3
-rw-r--r--lib/Settings/Admin/SignalingServer.php4
-rw-r--r--templates/settings/admin/signaling-server.php18
8 files changed, 166 insertions, 58 deletions
diff --git a/css/settings-admin.scss b/css/settings-admin.scss
index 1c7a0ba60..051e7d37f 100644
--- a/css/settings-admin.scss
+++ b/css/settings-admin.scss
@@ -6,6 +6,7 @@
.icon-delete,
.icon-checkmark-color,
div.stun-server:last-child .icon-add,
+ div.signaling-server:last-child .icon-add,
div.turn-server:last-child .icon-add {
display: inline-block;
}
diff --git a/js/admin/signaling-server.js b/js/admin/signaling-server.js
index d3e67a3ae..de066ee0d 100644
--- a/js/admin/signaling-server.js
+++ b/js/admin/signaling-server.js
@@ -1,28 +1,127 @@
/* global OC, OCP, OCA, $, _, Handlebars */
-(function(OC, OCP, OCA, $) {
+(function(OC, OCP, OCA, $, _, Handlebars) {
'use strict';
OCA.VideoCalls = OCA.VideoCalls || {};
OCA.VideoCalls.Admin = OCA.VideoCalls.Admin || {};
OCA.VideoCalls.Admin.SignalingServer = {
- $signaling: undefined,
+ TEMPLATE: '<div class="signaling-server">' +
+ ' <input type="text" class="server" placeholder="wss://signaling.example.org" value="{{server}}">' +
+ ' <input type="checkbox" id="verify{{seed}}" name="verify{{seed}}" class="checkbox verify" value="1" {{#if verify}} checked="checked"{{/if}}>' +
+ ' <label for="verify{{seed}}">' + t('spreed', 'Validate SSL certificate') + '</label>' +
+ ' <a class="icon icon-delete" title="' + t('spreed', 'Delete server') + '"></a>' +
+ ' <a class="icon icon-add" title="' + t('spreed', 'Add new server') + '"></a>' +
+ ' <span class="icon icon-checkmark-color hidden" title="' + t('spreed', 'Saved') + '"></span>' +
+ '</div>',
+ $list: undefined,
+ $secret: undefined,
+ template: undefined,
+ seed: 0,
init: function() {
- this.$signaling = $('div.signaling-server');
- this.$signaling.find('input').on('change', this.saveServer);
+ this.template = Handlebars.compile(this.TEMPLATE);
+ this.$list = $('div.signaling-servers');
+ this.$secret = $('#signaling_secret');
+ this.renderList();
+
+ this.$secret.on('change', this.saveServers.bind(this));
+ },
+
+ renderList: function() {
+ var data = this.$list.data('servers');
+
+ var hasServers = false;
+ if (!_.isUndefined(data.secret)) {
+ _.each(data.servers, function (server) {
+ this.$list.append(
+ this.renderServer(server)
+ );
+ }.bind(this));
+
+ hasServers = data.servers.length !== 0;
+
+ this.$secret.val(data.secret);
+ }
+
+ if (!hasServers) {
+ this.addNewTemplate();
+ }
+
+ this.$secret.parents('p').first().removeClass('hidden');
+ },
+
+ addNewTemplate: function() {
+ var $server = this.renderServer({
+ validate: true
+ });
+ this.$list.append($server);
+ return $server;
+ },
+
+ deleteServer: function(e) {
+ e.stopPropagation();
+
+ var $server = $(e.currentTarget).parents('div.signaling-server').first();
+ $server.remove();
+
+ this.saveServers();
+
+ if (this.$list.find('div.signaling-server').length === 0) {
+ var $newServer = this.addNewTemplate();
+ this.temporaryShowSuccess($newServer);
+ }
},
- saveServer: function() {
- // this.$signaling.find('input').removeClass('error');
- // this.$signaling.find('.icon-checkmark-color').addClass('hidden');
+ saveServers: function() {
+ var servers = [],
+ $error = [],
+ $success = [],
+ self = this,
+ $secret = this.$secret,
+ secret = this.$secret.val().trim();
+
+ this.$list.find('input').removeClass('error');
+ this.$secret.removeClass('error');
+ this.$list.find('.icon-checkmark-color').addClass('hidden');
+
+ this.$list.find('div.signaling-server').each(function() {
+ var $row = $(this),
+ $server = $row.find('input.server'),
+ $verify = $row.find('input.verify'),
+ data = {
+ server: $server.val().trim(),
+ verify: $verify.val() === '1'
+ };
+
+ if (data.server === '') {
+ $error.push($server);
+ return;
+ }
- // OCP.AppConfig.setValue('spreed', $(this).attr('name'), $(this).value, {
- // success: function() {
- // self.temporaryShowSuccess($server);
- // }
- // });
+ if (secret === '') {
+ $error.push($secret);
+ return;
+ }
+
+ $success.push($(this));
+ servers.push(data);
+ });
+
+ OCP.AppConfig.setValue('spreed', 'signaling_servers', JSON.stringify({
+ servers: servers,
+ secret: secret
+ }), {
+ success: function() {
+ _.each($error, function($input) {
+ $input.addClass('error');
+ });
+ _.each($success, function($server) {
+ self.temporaryShowSuccess($server);
+ });
+ }
+ });
},
temporaryShowSuccess: function($server) {
@@ -31,12 +130,23 @@
setTimeout(function() {
$icon.addClass('hidden');
}, 2000);
+ },
+
+ renderServer: function(server) {
+ server.seed = this.seed++;
+ var $template = $(this.template(server));
+
+ $template.find('a.icon-add').on('click', this.addNewTemplate.bind(this));
+ $template.find('a.icon-delete').on('click', this.deleteServer.bind(this));
+ $template.find('input').on('change', this.saveServers.bind(this));
+
+ return $template;
}
};
-})(OC, OCP, OCA, $);
+})(OC, OCP, OCA, $, _, Handlebars);
$(document).ready(function(){
OCA.VideoCalls.Admin.SignalingServer.init();
diff --git a/lib/BackendNotifier.php b/lib/BackendNotifier.php
index 14593de07..d91448897 100644
--- a/lib/BackendNotifier.php
+++ b/lib/BackendNotifier.php
@@ -74,11 +74,8 @@ class BackendNotifier{
}
// We can use any server of the available backends.
- $signaling = $signaling[array_rand($signaling)];
- if (substr($signaling, -1) === '/') {
- $signaling = substr($signaling, 0, strlen($signaling) - 1);
- }
- $url = $signaling . $url;
+ $signaling['server'] = rtrim($signaling['server'], '/');
+ $url = rtrim($signaling['server'], '/') . $url;
if (substr($url, 0, 6) === 'wss://') {
$url = 'https://' . substr($url, 6);
} else if (substr($url, 0, 5) === 'ws://') {
@@ -99,10 +96,10 @@ class BackendNotifier{
'headers' => $headers,
'body' => $body,
];
- if ($this->config->allowInsecureSignaling()) {
+ if (!$signaling['verify']) {
$params['verify'] = false;
}
- $response = $client->post($url, $params);
+ $client->post($url, $params);
}
/**
diff --git a/lib/Config.php b/lib/Config.php
index 5d5a72908..4bc04c79b 100644
--- a/lib/Config.php
+++ b/lib/Config.php
@@ -106,13 +106,19 @@ class Config {
}
/**
- * @return string
+ * @return array
*/
public function getSignalingServer() {
- $server = $this->config->getAppValue('spreed', 'signaling_server', '');
- if ($server === '') {
+ $config = $this->config->getAppValue('spreed', 'signaling_servers');
+ $signaling = json_decode($config, true);
+
+ if (!is_array($signaling)) {
return [];
}
+
+ // For now we use a random server from the list
+ $server = $signaling['servers'][mt_rand(0, count($servers) - 1)];
+
return explode('\n', $server);
}
@@ -120,15 +126,14 @@ class Config {
* @return string
*/
public function getSignalingSecret() {
- return $this->config->getAppValue('spreed', 'signaling_secret', '');
- }
+ $config = $this->config->getAppValue('spreed', 'signaling_servers');
+ $signaling = json_decode($config, true);
- /**
- * @return bool
- */
- public function allowInsecureSignaling() {
- $skip_verify = $this->config->getAppValue('spreed', 'signaling_skip_verify_cert', '');
- return !empty($skip_verify);
+ if (!is_array($signaling)) {
+ return '';
+ }
+
+ return $signaling['secret'];
}
/**
@@ -137,9 +142,9 @@ class Config {
*/
public function getSignalingTicket($userId) {
if (empty($userId)) {
- $secret = $this->config->getAppValue('spreed', 'signaling_ticket_secret', '');
+ $secret = $this->config->getAppValue('spreed', 'signaling_ticket_secret');
} else {
- $secret = $this->config->getUserValue($userId, 'spreed', 'signaling_ticket_secret', '');
+ $secret = $this->config->getUserValue($userId, 'spreed', 'signaling_ticket_secret');
}
if (empty($secret)) {
// Create secret lazily on first access.
@@ -168,24 +173,24 @@ class Config {
*/
public function validateSignalingTicket($userId, $ticket) {
if (empty($userId)) {
- $secret = $this->config->getAppValue('spreed', 'signaling_ticket_secret', '');
+ $secret = $this->config->getAppValue('spreed', 'signaling_ticket_secret');
} else {
- $secret = $this->config->getUserValue($userId, 'spreed', 'signaling_ticket_secret', '');
+ $secret = $this->config->getUserValue($userId, 'spreed', 'signaling_ticket_secret');
}
if (empty($secret)) {
return false;
}
- $lastcolon = strrpos($ticket, ':');
- if ($lastcolon === false) {
+ $lastColon = strrpos($ticket, ':');
+ if ($lastColon === false) {
// Immediately reject invalid formats.
return false;
}
// TODO(fancycode): Should we reject tickets that are too old?
- $data = substr($ticket, 0, $lastcolon);
+ $data = substr($ticket, 0, $lastColon);
$hash = hash_hmac('sha256', $data, $secret);
- return hash_equals($hash, substr($ticket, $lastcolon + 1));
+ return hash_equals($hash, substr($ticket, $lastColon + 1));
}
}
diff --git a/lib/Controller/PageController.php b/lib/Controller/PageController.php
index 6663829b4..190cae082 100644
--- a/lib/Controller/PageController.php
+++ b/lib/Controller/PageController.php
@@ -116,8 +116,14 @@ class PageController extends Controller {
];
}
}
+
+ $signaling = $this->config->getSignalingServer();
+ if (!empty($signaling)) {
+ $signaling = $signaling['server'];
+ }
+
return [
- 'server' => $this->config->getSignalingServer(),
+ 'server' => $signaling,
'ticket' => $this->config->getSignalingTicket($this->userId),
'stunservers' => $stun,
'turnservers' => $turn,
diff --git a/lib/Controller/SignalingController.php b/lib/Controller/SignalingController.php
index ee6efc9e5..947f437e5 100644
--- a/lib/Controller/SignalingController.php
+++ b/lib/Controller/SignalingController.php
@@ -215,7 +215,7 @@ class SignalingController extends OCSController {
return $usersInRoom;
}
- /*
+ /**
* Check if the current request is coming from an allowed backend.
*
* The backends are sending the custom header "Spreed-Signaling-Random"
@@ -249,7 +249,6 @@ class SignalingController extends OCSController {
* @NoCSRFRequired
* @PublicPage
*
- * @param string $message
* @return JSONResponse
*/
public function backend() {
diff --git a/lib/Settings/Admin/SignalingServer.php b/lib/Settings/Admin/SignalingServer.php
index 739f9e55d..c5ad31d93 100644
--- a/lib/Settings/Admin/SignalingServer.php
+++ b/lib/Settings/Admin/SignalingServer.php
@@ -40,9 +40,7 @@ class SignalingServer implements ISettings {
*/
public function getForm() {
$parameters = [
- 'signalingServer' => $this->config->getAppValue('spreed', 'signaling_server'),
- 'signalingSecret' => $this->config->getAppValue('spreed', 'signaling_secret'),
- 'signalingSkipVerifyCert' => $this->config->getAppValue('spreed', 'signaling_skip_verify_cert'),
+ 'signalingServers' => $this->config->getAppValue('spreed', 'signaling_servers'),
];
return new TemplateResponse('spreed', 'settings/admin/signaling-server', $parameters, '');
diff --git a/templates/settings/admin/signaling-server.php b/templates/settings/admin/signaling-server.php
index b07e2a566..d078f93c2 100644
--- a/templates/settings/admin/signaling-server.php
+++ b/templates/settings/admin/signaling-server.php
@@ -9,21 +9,13 @@ style('spreed', ['settings-admin']);
<h3><?php p($l->t('Signaling server')) ?></h3>
<p class="settings-hint"><?php p($l->t('An external signaling server can optionally be used for larger installations. Leave empty to use the internal signaling server.')) ?></p>
- <p>
- <label for="signaling_server"><?php p($l->t('External signaling server')) ?></label>
- <input type="text" id="signaling_server"
- name="signaling_server" placeholder="wss://signaling.example.org"
- value="<?php p($_['signalingServer']) ?>" />
- </p>
- <p>
- <input type="checkbox" id="signaling_skip_verify_cert" name="signaling_skip_verify_cert" class="checkbox" value="1" <?php p($_['signalingSkipVerifyCert'] ? 'checked="checked"' : '') ?>>
- <label for="signaling_skip_verify_cert"><?php p($l->t('Allow invalid certificates when connecting to the external signaling server? Only enable this if required for development!')) ?>
- </label>
- </p>
- <p>
+ <div class="signaling-servers" data-servers="<?php p($_['signalingServers']) ?>">
+ </div>
+
+ <p class="hidden">
<label for="signaling_secret"><?php p($l->t('Shared secret')) ?></label>
<input type="text" id="signaling_secret"
- name="signaling_secret" placeholder="shared secret"
+ name="signaling_secret" placeholder="<?php p($l->t('Shared secret')) ?>"
value="<?php p($_['signalingSecret']) ?>" />
</p>
</div>