mirror of https://github.com/sualko/cloud_bbb
parent
a72c877f6b
commit
5debcb6d2a
|
@ -14,6 +14,7 @@ use OCA\BigBlueButton\Event\MeetingStartedEvent;
|
|||
use OCA\BigBlueButton\Db\Room;
|
||||
use OCA\BigBlueButton\Permission;
|
||||
use OCA\BigBlueButton\Crypto;
|
||||
use OCA\BigBlueButton\UrlHelper;
|
||||
use OCP\IConfig;
|
||||
use OCP\IURLGenerator;
|
||||
use OCP\IL10N;
|
||||
|
@ -40,13 +41,17 @@ class API {
|
|||
/** @var IL10N */
|
||||
private $l10n;
|
||||
|
||||
/** @var UrlHelper */
|
||||
private $urlHelper;
|
||||
|
||||
public function __construct(
|
||||
IConfig $config,
|
||||
IURLGenerator $urlGenerator,
|
||||
Permission $permission,
|
||||
Crypto $crypto,
|
||||
IEventDispatcher $eventDispatcher,
|
||||
IL10N $l10n
|
||||
IL10N $l10n,
|
||||
UrlHelper $urlHelper
|
||||
) {
|
||||
$this->config = $config;
|
||||
$this->urlGenerator = $urlGenerator;
|
||||
|
@ -54,6 +59,7 @@ class API {
|
|||
$this->crypto = $crypto;
|
||||
$this->eventDispatcher = $eventDispatcher;
|
||||
$this->l10n = $l10n;
|
||||
$this->urlHelper = $urlHelper;
|
||||
}
|
||||
|
||||
private function getServer() {
|
||||
|
@ -132,7 +138,7 @@ class API {
|
|||
$recordingReadyUrl = $this->urlGenerator->linkToRouteAbsolute('bbb.hook.recordingReady', ['token' => $room->uid, 'mac' => $mac]);
|
||||
$createMeetingParams->setRecordingReadyCallbackUrl($recordingReadyUrl);
|
||||
|
||||
$invitationUrl = $this->urlGenerator->linkToRouteAbsolute('bbb.join.index', ['token' => $room->uid]);
|
||||
$invitationUrl = $this->urlHelper->linkToInvitationAbsolute($room);
|
||||
$createMeetingParams->setModeratorOnlyMessage($this->l10n->t('To invite someone to the meeting, send them this link: %s', [$invitationUrl]));
|
||||
|
||||
if (!empty($room->welcome)) {
|
||||
|
|
|
@ -5,10 +5,16 @@ namespace OCA\BigBlueButton\Controller;
|
|||
use OCP\IRequest;
|
||||
use OCP\AppFramework\Http\TemplateResponse;
|
||||
use OCP\AppFramework\Controller;
|
||||
use OCP\IConfig;
|
||||
|
||||
class PageController extends Controller {
|
||||
public function __construct(string $appName, IRequest $request) {
|
||||
/** @var IConfig */
|
||||
private $config;
|
||||
|
||||
public function __construct(string $appName, IRequest $request, IConfig $config) {
|
||||
parent::__construct($appName, $request);
|
||||
|
||||
$this->config = $config;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -16,6 +22,8 @@ class PageController extends Controller {
|
|||
* @NoCSRFRequired
|
||||
*/
|
||||
public function index() {
|
||||
return new TemplateResponse($this->appName, 'manager');
|
||||
return new TemplateResponse($this->appName, 'manager', [
|
||||
'shortener' => $this->config->getAppValue('bbb', 'app.shortener', ''),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ class Admin implements ISettings {
|
|||
'api.url' => $this->config->getAppValue('bbb', 'api.url'),
|
||||
'api.secret' => $this->config->getAppValue('bbb', 'api.secret'),
|
||||
'app.navigation' => $this->config->getAppValue('bbb', 'app.navigation') === 'true' ? 'checked' : '',
|
||||
'app.shortener' => $this->config->getAppValue('bbb', 'app.shortener'),
|
||||
];
|
||||
|
||||
return new TemplateResponse('bbb', 'admin', $parameters);
|
||||
|
|
|
@ -34,7 +34,10 @@ class Personal implements ISettings {
|
|||
$warning = $this->l->t('API URL or secret not configured. Please contact your administrator.');
|
||||
}
|
||||
|
||||
return new TemplateResponse('bbb', 'manager', ['warning' => $warning]);
|
||||
return new TemplateResponse('bbb', 'manager', [
|
||||
'warning' => $warning,
|
||||
'shortener' => $this->config->getAppValue('bbb', 'app.shortener', ''),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
<?php
|
||||
|
||||
namespace OCA\BigBlueButton;
|
||||
|
||||
use OCA\BigBlueButton\Db\Room;
|
||||
use OCP\IConfig;
|
||||
use OCP\IURLGenerator;
|
||||
|
||||
class UrlHelper {
|
||||
/** @var IConfig */
|
||||
private $config;
|
||||
|
||||
/** @var IURLGenerator */
|
||||
private $urlGenerator;
|
||||
|
||||
public function __construct(
|
||||
IConfig $config,
|
||||
IURLGenerator $urlGenerator
|
||||
) {
|
||||
$this->config = $config;
|
||||
$this->urlGenerator = $urlGenerator;
|
||||
}
|
||||
|
||||
public function linkToInvitationAbsolute(Room $room): string {
|
||||
$url = $this->config->getAppValue('bbb', 'app.shortener', '');
|
||||
|
||||
if (empty($url) || strpos($url, 'https://') !== 0 || strpos($url, '{token}') === false) {
|
||||
return $this->urlGenerator->linkToRouteAbsolute('bbb.join.index', ['token' => $room->getUid()]);
|
||||
}
|
||||
|
||||
$placeholders = [];
|
||||
$replacements = [
|
||||
'token' => $room->getUid(),
|
||||
'user' => $room->getUserId(),
|
||||
];
|
||||
|
||||
|
||||
foreach ($replacements as $placeholder => $parameter) {
|
||||
$placeholders[] = '{' . $placeholder . '}';
|
||||
}
|
||||
|
||||
return str_replace($placeholders, $replacements, $url);
|
||||
}
|
||||
}
|
|
@ -11,12 +11,12 @@ script('bbb', 'restrictions');
|
|||
|
||||
<p><?php p($l->t('Get your API URL and secret by executing "sudo bbb-conf --secret" on your BigBlueButton server.')); ?></p>
|
||||
|
||||
<form>
|
||||
<form id="bbb-api">
|
||||
<input type="url" name="api.url" value="<?php p($_['api.url']); ?>" placeholder="<?php p($l->t('API URL')); ?>" pattern="https://.*" required />
|
||||
<input type="password" name="api.secret" value="<?php p($_['api.secret']); ?>" placeholder="<?php p($l->t('API secret')); ?>" autocomplete="new-password" required />
|
||||
<input type="submit" value="<?php p($l->t('Save')); ?>" />
|
||||
|
||||
<div id="bbb-result"></div>
|
||||
<div class="bbb-result"></div>
|
||||
</form>
|
||||
|
||||
<p>
|
||||
|
@ -24,6 +24,18 @@ script('bbb', 'restrictions');
|
|||
<label for="bbb-app-navigation"><?php p($l->t('Show room manager in app navigation instead of settings page.')); ?></label>
|
||||
</p>
|
||||
|
||||
<h3>URL Shortener</h3>
|
||||
<p><?php p($l->t('If you like to use shorter urls, you can enter a forwarding proxy below.')); ?></p>
|
||||
|
||||
<form id="bbb-shortener">
|
||||
<input type="url" name="app.shortener" value="<?php p($_['app.shortener']); ?>" placeholder="<?php p($l->t('URL shortener')); ?>" pattern="https://.*" />
|
||||
<input type="submit" value="<?php p($l->t('Save')); ?>" />
|
||||
|
||||
<div id="bbb-shortener-example"></div>
|
||||
|
||||
<div class="bbb-result"></div>
|
||||
</form>
|
||||
|
||||
<h3>Restrictions</h3>
|
||||
<div id="bbb-restrictions">
|
||||
</div>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
script('bbb', 'manager');
|
||||
?>
|
||||
|
||||
<div id="bbb-root"></div>
|
||||
<div id="bbb-root" data-shortener="<?php p($_[shortener]); ?>"></div>
|
||||
|
||||
<?php if (!empty($_['warning'])): ?>
|
||||
<div id="bbb-warning">
|
||||
|
|
|
@ -122,6 +122,12 @@ class Api {
|
|||
}
|
||||
|
||||
public getRoomUrl(room: Room) {
|
||||
const shortener = document.getElementById('bbb-root')?.getAttribute('data-shortener') || '';
|
||||
|
||||
if (shortener) {
|
||||
return shortener.replace(/\{user\}/g, room.userId).replace(/\{token\}/g, room.uid);
|
||||
}
|
||||
|
||||
return window.location.origin + api.getUrl(`b/${room.uid}`);
|
||||
}
|
||||
|
||||
|
|
|
@ -27,6 +27,14 @@
|
|||
width: 100%;
|
||||
}
|
||||
|
||||
pre {
|
||||
font-weight: normal;
|
||||
background-color: #f1f1f1;
|
||||
padding: 1em 2em;
|
||||
display: inline-block;
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
#bbb-warning {
|
||||
padding: 1em;
|
||||
background-color: rgb(255, 255, 123);
|
||||
|
|
|
@ -187,10 +187,10 @@ const RoomRow: React.FC<Props> = (props) => {
|
|||
<>
|
||||
<tr className={showRecordings ? 'selected-row' : ''}>
|
||||
<td className="start icon-col">
|
||||
<a href={api.getUrl(`b/${room.uid}`)} className="icon icon-play icon-visible" target="_blank" rel="noopener noreferrer"></a>
|
||||
<a href={api.getRoomUrl(room)} className="icon icon-play icon-visible" target="_blank" rel="noopener noreferrer"></a>
|
||||
</td>
|
||||
<td className="share icon-col">
|
||||
<CopyToClipboard text={window.location.origin + api.getUrl(`b/${room.uid}`)}>
|
||||
<CopyToClipboard text={api.getRoomUrl(room)}>
|
||||
<span className="icon icon-clippy icon-visible copy-to-clipboard" ></span>
|
||||
</CopyToClipboard>
|
||||
</td>
|
||||
|
|
95
ts/admin.ts
95
ts/admin.ts
|
@ -34,7 +34,7 @@ $(() => {
|
|||
});
|
||||
}
|
||||
|
||||
async function saveSettings(url: string, secret: string) {
|
||||
async function saveApiSettings(url: string, secret: string) {
|
||||
url += url.endsWith('/') ? '' : '/';
|
||||
|
||||
await checkServer(url, secret);
|
||||
|
@ -44,19 +44,19 @@ $(() => {
|
|||
OCP.AppConfig.setValue('bbb', 'api.secret', secret);
|
||||
}
|
||||
|
||||
$('#bbb-settings form').submit(function (ev) {
|
||||
$('#bbb-api').on('submit', function (ev) {
|
||||
ev.preventDefault();
|
||||
|
||||
$('#bbb-result').empty();
|
||||
const resultElement = $(this).find('.bbb-result').empty();
|
||||
|
||||
saveSettings(this['api.url'].value, this['api.secret'].value).then(() => {
|
||||
saveApiSettings(this['api.url'].value, this['api.secret'].value).then(() => {
|
||||
const successElement = generateSuccessElement(t('bbb', 'Settings saved'));
|
||||
|
||||
setTimeout(() => {
|
||||
$('#bbb-result').empty();
|
||||
resultElement.empty();
|
||||
}, 3000);
|
||||
|
||||
$('#bbb-result').append(successElement);
|
||||
resultElement.append(successElement);
|
||||
}).catch(err => {
|
||||
let message = t('bbb', 'Unexpected error occurred');
|
||||
|
||||
|
@ -68,11 +68,90 @@ $(() => {
|
|||
|
||||
const warningElement = generateWarningElement(message);
|
||||
|
||||
$('#bbb-result').append(warningElement);
|
||||
resultElement.append(warningElement);
|
||||
});
|
||||
});
|
||||
|
||||
$<HTMLInputElement>('#bbb-settings [name="app.navigation"]').change((ev) => {
|
||||
function generateExampleShortener(shortener: string) {
|
||||
return shortener.replace(/</g, '<').replace(/\{user\}/g, `<strong>${OC.currentUser}</strong>`).replace(/\{token\}/g, '<strong>your_room_id</strong>');
|
||||
}
|
||||
|
||||
async function saveAppSettings(shortener: string) {
|
||||
await checkPasswordConfirmation();
|
||||
|
||||
if (shortener.indexOf('https://') !== 0) {
|
||||
throw 'https';
|
||||
}
|
||||
|
||||
if (shortener.indexOf('{token}') < 0) {
|
||||
throw 'token';
|
||||
}
|
||||
|
||||
OCP.AppConfig.setValue('bbb', 'app.shortener', shortener);
|
||||
}
|
||||
|
||||
$('#bbb-shortener').on('submit', function (ev) {
|
||||
ev.preventDefault();
|
||||
|
||||
const resultElement = $(this).find('.bbb-result').empty();
|
||||
|
||||
saveAppSettings(this['app.shortener'].value).then(() => {
|
||||
const successElement = generateSuccessElement(t('bbb', 'Settings saved'));
|
||||
|
||||
setTimeout(() => {
|
||||
resultElement.empty();
|
||||
}, 3000);
|
||||
|
||||
resultElement.append(successElement);
|
||||
}).catch(err => {
|
||||
let message = t('bbb', 'Unexpected error occurred');
|
||||
|
||||
if (err === 'https') {
|
||||
message = t('bbb', 'URL has to start with https');
|
||||
} else if (err === 'token') {
|
||||
message = t('bbb', 'URL has to contain the {token} placeholder');
|
||||
}
|
||||
|
||||
const warningElement = generateWarningElement(message);
|
||||
|
||||
console.warn('Could not save app settings', err);
|
||||
|
||||
resultElement.append(warningElement);
|
||||
});
|
||||
});
|
||||
|
||||
$<HTMLInputElement>('#bbb-shortener [name="app.shortener"]').on('keyup', (ev) => {
|
||||
ev.preventDefault();
|
||||
|
||||
const {value} = ev.target;
|
||||
|
||||
if (!value || value.indexOf('https://') !== 0 || value.indexOf('{token}') < 0) {
|
||||
$('#bbb-shortener-example').text(t('bbb', 'URL has to start with https:// and contain {token}. Additionally the {user} placeholder can be used.'));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const target = window.location.origin + OC.generateUrl('apps/bbb/b/$1');
|
||||
const url = (new URL(value));
|
||||
const rewritePath = '^' + url.pathname.replace(/^\//, '').replace(/%7Buser%7D/g, '.+').replace(/%7Btoken%7D/g, '(.+)');
|
||||
|
||||
$('#bbb-shortener-example').html(`<p>${generateExampleShortener(value)}</p>
|
||||
<details>
|
||||
<summary>${t('bbb', 'Example configuration for Apache and Nginx')}</summary>
|
||||
<pre>#Apache with mod_rewrite
|
||||
ServerName ${url.hostname}
|
||||
RewriteEngine on
|
||||
RewriteRule "${rewritePath}" "${target}" [R=307,L]
|
||||
|
||||
#Nginx config
|
||||
server_name ${url.hostname};
|
||||
rewrite ${rewritePath} ${target} last;
|
||||
return 307;</pre></details>
|
||||
`);
|
||||
});
|
||||
$('#bbb-shortener [name="app.shortener"]').trigger('keyup');
|
||||
|
||||
$<HTMLInputElement>('#bbb-settings [name="app.navigation"]').on('change', (ev) => {
|
||||
ev.preventDefault();
|
||||
|
||||
console.log('checkbox changed to', ev.target.checked);
|
||||
|
|
Loading…
Reference in New Issue