feat: add api check

- show result
- show if url or secret is invalid
- add trailing slash to url
pull/36/head
sualko 2020-05-17 13:39:01 +02:00
parent e147019dbe
commit a1ffa4c4e3
8 changed files with 170 additions and 5 deletions

View File

@ -6,6 +6,8 @@ return [
], ],
'routes' => [ 'routes' => [
['name' => 'server#records', 'url' => '/server/{roomUid}/records', 'verb' => 'GET'], ['name' => 'server#records', 'url' => '/server/{roomUid}/records', 'verb' => 'GET'],
['name' => 'server#check', 'url' => '/server/check', 'verb' => 'POST'],
['name' => 'server#version', 'url' => '/server/version', 'verb' => 'GET'],
['name' => 'server#delete_record', 'url' => '/server/record/{recordId}', 'verb' => 'DELETE'], ['name' => 'server#delete_record', 'url' => '/server/record/{recordId}', 'verb' => 'DELETE'],
['name' => 'join#index', 'url' => '/b/{token}', 'verb' => 'GET'], ['name' => 'join#index', 'url' => '/b/{token}', 'verb' => 'GET'],
['name' => 'room_api#preflighted_cors', 'url' => '/api/0.1/{path}', ['name' => 'room_api#preflighted_cors', 'url' => '/api/0.1/{path}',

View File

@ -8,6 +8,7 @@ use BigBlueButton\Parameters\JoinMeetingParameters;
use BigBlueButton\Parameters\GetRecordingsParameters; use BigBlueButton\Parameters\GetRecordingsParameters;
use BigBlueButton\Core\Record; use BigBlueButton\Core\Record;
use BigBlueButton\Parameters\DeleteRecordingsParameters; use BigBlueButton\Parameters\DeleteRecordingsParameters;
use BigBlueButton\Parameters\IsMeetingRunningParameters;
use OCA\BigBlueButton\Db\Room; use OCA\BigBlueButton\Db\Room;
use OCP\IConfig; use OCP\IConfig;
use OCP\IURLGenerator; use OCP\IURLGenerator;
@ -180,4 +181,34 @@ class API
'metas' => $record->getMetas(), 'metas' => $record->getMetas(),
]; ];
} }
public function check($url, $secret)
{
$server = new BigBlueButton($url, $secret);
$meetingParams = new IsMeetingRunningParameters('foobar');
try {
$response = $server->isMeetingRunning($meetingParams);
if (!$response->success() && !$response->failed()) {
return 'invalid-url';
}
if (!$response->success()) {
return 'invalid-secret';
}
return 'success';
} catch (\Exception $e) {
return 'invalid-url';
}
}
public function getVersion($url = null)
{
$server = $url === null ? $this->getServer() : new BigBlueButton($url, '');
return $server->getApiVersion()->getVersion();
}
} }

View File

@ -76,4 +76,28 @@ class ServerController extends Controller
return new DataResponse($success); return new DataResponse($success);
} }
public function check(string $url, string $secret)
{
if ($url === null || empty($url) || $secret === null || empty($secret)) {
return new DataResponse(false);
}
return new DataResponse($this->server->check($url, $secret));
}
public function version(string $url)
{
if ($url === null || empty($url)) {
return new DataResponse(false, Http::STATUS_NOT_FOUND);
}
try {
$version = $this->server->getVersion($url);
} catch (\Exception $e) {
return new DataResponse(false, Http::STATUS_NOT_FOUND);
}
return new DataResponse($version);
}
} }

View File

@ -8,9 +8,13 @@ script('bbb', 'admin');
<div id="bbb-settings" class="section"> <div id="bbb-settings" class="section">
<h2>BigBlueButton</h2> <h2>BigBlueButton</h2>
<p><?php p($l->t('Get your API url and secret by executing "sudo bbb-conf --secret" on your BigBlueButton server.')); ?></p>
<form> <form>
<input type="url" name="api.url" value="<?php p($_['api.url']); ?>" placeholder="<?php p($l->t('API url')); ?>" pattern="https://.*" /> <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" /> <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')); ?>" /> <input type="submit" value="<?php p($l->t('Save')); ?>" />
<div id="bbb-result"></div>
</form> </form>
</div> </div>

View File

@ -75,6 +75,15 @@ class Api {
return response.data; return response.data;
} }
public async checkServer(url: string, secret: string): Promise<'success'|'invalid-url'|'invalid:secret'> {
const response = await axios.post(this.getUrl('server/check'), {
url,
secret,
});
return response.data;
}
} }
export const api = new Api(); export const api = new Api();

View File

@ -1,5 +1,4 @@
#bbb-warning { #bbb-warning {
margin: 3em;
padding: 1em; padding: 1em;
background-color: rgb(255, 255, 123); background-color: rgb(255, 255, 123);
display: inline-block; display: inline-block;
@ -9,7 +8,37 @@
} }
} }
#bbb-success {
padding: 1em;
background-color: rgb(176, 252, 132);
display: inline-block;
.icon {
display: inline-block;
}
}
#bbb-settings {
#bbb-warning,
#bbb-success {
margin: 1em 0;
}
[type="url"],
[type="password"] {
width: 250px;
}
p {
margin-bottom: 1em;
}
}
#bbb-react-root { #bbb-react-root {
#bbb-warning,
#bbb-success {
margin: 3em;
}
.icon { .icon {
display: inline-block; display: inline-block;

View File

@ -46,6 +46,12 @@ declare namespace OC {
} }
} }
namespace PasswordConfirmation {
function requiresPasswordConfirmation(): boolean;
function requirePasswordConfirmation(cb: () => void): void;
}
function generateUrl(url: string, parameters?: { [key: string]: string }, options?: EscapeOptions) function generateUrl(url: string, parameters?: { [key: string]: string }, options?: EscapeOptions)
function linkToOCS(service: string, version: number): string; function linkToOCS(service: string, version: number): string;

View File

@ -1,10 +1,70 @@
import {api} from './Manager/Api';
import './Manager/App.scss';
declare const OCP: any; declare const OCP: any;
$(() => { $(() => {
function generateWarningElement(message: string) {
return $(`<div id="bbb-warning"><span class="icon icon-error-color icon-visible"></span> ${message}</div>`);
}
function generateSuccessElement(message: string) {
return $(`<div id="bbb-success"><span class="icon icon-checkmark-color icon-visible"></span> ${message}</div>`);
}
async function checkServer(url: string, secret: string) {
const result = await api.checkServer(url, secret);
if (result === 'success') {
return;
}
throw result;
}
function checkPasswordConfirmation() {
return new Promise(resolve => {
if (OC.PasswordConfirmation && OC.PasswordConfirmation.requiresPasswordConfirmation()) {
OC.PasswordConfirmation.requirePasswordConfirmation(() => resolve());
return;
}
resolve();
});
}
async function saveSettings(url: string, secret: string) {
url += url.endsWith('/') ? '' : '/';
await checkServer(url, secret);
await checkPasswordConfirmation();
OCP.AppConfig.setValue('bbb', 'api.url', url);
OCP.AppConfig.setValue('bbb', 'api.secret', secret);
}
$('#bbb-settings form').submit(function (ev) { $('#bbb-settings form').submit(function (ev) {
ev.preventDefault(); ev.preventDefault();
OCP.AppConfig.setValue('bbb', 'api.url', this['api.url'].value); $('#bbb-result').empty();
OCP.AppConfig.setValue('bbb', 'api.secret', this['api.secret'].value);
saveSettings(this['api.url'].value, this['api.secret'].value).then(() => {
const successElement = generateSuccessElement(t('bbb', 'Settings saved'));
$('#bbb-result').append(successElement);
}).catch(err => {
let message = t('bbb', 'Unexpected error occurred');
if (err === 'invalid-url') {
message = t('bbb', 'API url is invalid');
} else if (err === 'invalid-secret') {
message = t('bbb', 'API secret is invalid');
}
const warningElement = generateWarningElement(message);
$('#bbb-result').append(warningElement);
});
}); });
}); });