Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ tests
.phpunit.result.cache
.styleci.yml
phpunit.xml
docs
ssl
db
redis
Expand Down
1 change: 1 addition & 0 deletions app/Console/Kernel.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ protected function schedule(Schedule $schedule): void
$schedule->command('telescope:prune')->daily()->onOneServer();
$schedule->command('horizon:snapshot')->everyFiveMinutes()->onOneServer();
$schedule->command(ImportRecordingsCommand::class)->everyMinute()->withoutOverlapping()->onOneServer();
$schedule->command('passport:purge')->hourly()->onOneServer();
}

/**
Expand Down
14 changes: 14 additions & 0 deletions app/Exceptions/Handler.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
use Laravel\Passport\Exceptions\MissingScopeException;
use Psr\Log\LogLevel;
use Spatie\LaravelIgnition\Exceptions\ViewException;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Throwable;

Expand Down Expand Up @@ -97,4 +99,16 @@ public function register(): void
}
});
}

public function render($request, Throwable $e): Response
{
// Overwrite default rendering of the MissingScopeException
if ($e instanceof MissingScopeException) {
return response()->json([
'message' => 'Missing required scope(s): '.implode(', ', $e->scopes()),
], 403);
}

return parent::render($request, $e);
}
}
22 changes: 22 additions & 0 deletions app/Http/Controllers/api/v1/OAuthAuthorizationController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

declare(strict_types=1);

namespace App\Http\Controllers\api\v1;

use Illuminate\Http\Request;
use Laravel\Passport\Contracts\AuthorizationViewResponse;
use Laravel\Passport\Http\Controllers\AuthorizationController;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Symfony\Component\HttpFoundation\Response;

class OAuthAuthorizationController extends AuthorizationController
{
public function authorize(ServerRequestInterface $psrRequest, Request $request, ResponseInterface $psrResponse, AuthorizationViewResponse $viewResponse): Response|AuthorizationViewResponse
{
$this->guard = auth()->guard();

return parent::authorize($psrRequest, $request, $psrResponse, $viewResponse);
}
}
34 changes: 34 additions & 0 deletions app/Http/Controllers/api/v1/OAuthTokenController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

declare(strict_types=1);

namespace App\Http\Controllers\api\v1;

use App\Http\Controllers\Controller;
use App\Http\Resources\OAuthTokenResource;
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
use Illuminate\Support\Facades\Auth;

class OAuthTokenController extends Controller
{
public function index(): AnonymousResourceCollection
{
$tokens = Auth::user()->oauthTokens()
->where('revoked', false)
->orderByDesc('created_at')
->get();

return OAuthTokenResource::collection($tokens);
}

public function destroy(string $token)
{
$oauthToken = Auth::user()->oauthTokens()->findOrFail($token);

$oauthToken->revoke();

$oauthToken->refreshToken?->revoke();

return response()->noContent();
}
}
16 changes: 16 additions & 0 deletions app/Http/Controllers/external/v1/CurrentTokenController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

declare(strict_types=1);

namespace App\Http\Controllers\external\v1;

use App\Http\Controllers\Controller;
use App\Http\Resources\External\CurrentUserResource;

class CurrentTokenController extends Controller
{
public function show()
{
return CurrentUserResource::make(auth()->user());
}
}
51 changes: 51 additions & 0 deletions app/Http/Controllers/external/v1/RoomController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php

declare(strict_types=1);

namespace App\Http\Controllers\external\v1;

use App\Http\Controllers\Controller;
use App\Http\Requests\External\CreateRoomRequest;
use App\Http\Resources\External\RoomResource;
use App\Models\Room;
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
use Illuminate\Support\Facades\Auth;

class RoomController extends Controller
{
public function __construct()
{
$this->authorizeResource(Room::class, 'room');
}

public function index(): AnonymousResourceCollection
{
$rooms = Room::query()
->where('user_id', Auth::id())
->with('roomType')
->orderByRaw('LOWER(name)')
->orderBy('id')
->get();

return RoomResource::collection($rooms);
}

public function store(CreateRoomRequest $request): RoomResource
{
if (Auth::user()->hasRoomLimitExceeded()) {
abort(429, __('app.errors.room_limit_exceeded'));
}

$room = new Room;
$room->name = $request->validated('name');
$room->access_code = $request->validated('access_code');
$room->allow_guests = (bool) $request->validated('allow_guests');
$room->roomType()->associate($request->validated('room_type'));
$room->owner()->associate(Auth::user());
$room->save();

$room->save();

return new RoomResource($room);
}
}
31 changes: 31 additions & 0 deletions app/Http/Controllers/external/v1/RoomTypeController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

declare(strict_types=1);

namespace App\Http\Controllers\external\v1;

use App\Http\Controllers\Controller;
use App\Http\Requests\External\RoomTypeIndexRequest;
use App\Http\Resources\External\RoomTypeResource;
use App\Models\RoomType;
use Illuminate\Support\Facades\Auth;

class RoomTypeController extends Controller
{
public function index(RoomTypeIndexRequest $request)
{
$roomTypes = RoomType::query();

if ($request->query('filter') === 'own') {
// Get list of the room type the current user has access to (Used when creating a new room)
$roomTypes = $roomTypes->where('restrict', '=', false)
->orWhereIn('id', function ($query) {
$query->select('role_room_type.room_type_id')
->from('role_room_type as role_room_type')
->whereIn('role_room_type.role_id', Auth::user()->roles->pluck('id')->all());
});
}

return RoomTypeResource::collection($roomTypes->get());
}
}
11 changes: 11 additions & 0 deletions app/Http/Kernel.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,14 @@
use Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull;
use Illuminate\Foundation\Http\Middleware\InvokeDeferredCallbacks;
use Illuminate\Foundation\Http\Middleware\ValidatePostSize;
use Illuminate\Http\Middleware\HandleCors;
use Illuminate\Http\Middleware\SetCacheHeaders;
use Illuminate\Routing\Middleware\SubstituteBindings;
use Illuminate\Routing\Middleware\ThrottleRequests;
use Illuminate\Routing\Middleware\ValidateSignature;
use Illuminate\Session\Middleware\StartSession;
use Illuminate\View\Middleware\ShareErrorsFromSession;
use Laravel\Passport\Http\Middleware\CheckToken;
use Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful;

class Kernel extends HttpKernel
Expand All @@ -52,6 +54,7 @@ class Kernel extends HttpKernel
InvokeDeferredCallbacks::class,
TrustHosts::class,
TrustProxies::class,
HandleCors::class,
PreventRequestsDuringMaintenance::class,
ValidatePostSize::class,
TrimStrings::class,
Expand Down Expand Up @@ -89,6 +92,13 @@ class Kernel extends HttpKernel
SetApplicationLocale::class,
LogContext::class,
],

'external_api' => [
ThrottleRequests::class.':external_api',
SubstituteBindings::class,
SetApplicationLocale::class,
LogContext::class,
],
];

/**
Expand All @@ -113,5 +123,6 @@ class Kernel extends HttpKernel
'check.stale' => EnsureModelNotStale::class,
'enable_if_config' => RouteEnableIfConfig::class,
'shibboleth' => ShibbolethSessionMiddleware::class,
'scope' => CheckToken::class,
];
}
24 changes: 24 additions & 0 deletions app/Http/Middleware/ApiRedirectMiddleware.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

declare(strict_types=1);

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;

class ApiRedirectMiddleware
{
public function handle(Request $request, Closure $next)
{
$response = $next($request);

if ($response->isRedirection()) {
return response()->json([
'redirect' => $response->headers->get('Location'),
]);
}

return $response;
}
}
1 change: 1 addition & 0 deletions app/Http/Middleware/PreventRequestForgery.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,6 @@ class PreventRequestForgery extends Middleware
protected $except = [
'auth/shibboleth/logout',
'auth/oidc/logout',
'oauth/token',
];
}
71 changes: 71 additions & 0 deletions app/Http/Requests/External/CreateRoomRequest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<?php

declare(strict_types=1);

namespace App\Http\Requests\External;

use App\Models\Room;
use App\Models\RoomType;
use App\Rules\ValidRoomType;
use Illuminate\Contracts\Validation\ValidationRule;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Facades\Auth;

class CreateRoomRequest extends FormRequest
{
/**
* Get the validation rules that apply to the request.
*
* @return array<string, ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
$rules = [
'name' => ['required', 'string', 'min:2', 'max:'.config('bigbluebutton.room_name_limit')],
'room_type' => ['bail', 'required', 'integer', 'exists:App\Models\RoomType,id', new ValidRoomType(Auth::user())],
'access_code' => $this->getAccessCodeValidationRule(),
'allow_guests' => $this->getRoomSettingValidationRule('allow_guests'),
];

return $rules;
}

private function getAccessCodeValidationRule(): array
{
$rules = ['string', 'numeric', 'digits:9', 'bail'];

// Make sure that the given room type id is a number
if (is_numeric($this->input('room_type'))) {
// Check if a room type exists with the given number
$newRoomType = RoomType::find($this->input('room_type'));
if ($newRoomType) {
// Set access code to required if enforced in room type
if ($newRoomType->has_access_code_enforced && $newRoomType->has_access_code_default) {
array_unshift($rules, 'required');
}
// Set access code to prohibited if enforced in room type
elseif ($newRoomType->has_access_code_enforced && ! $newRoomType->has_access_code_default) {
array_unshift($rules, 'prohibited', 'nullable');
}
// Set access code to nullable (room can have an access code but access code is not enforced)
else {
array_unshift($rules, 'nullable');
}
}
}

return $rules;
}

private function getRoomSettingValidationRule(string $settingName): array
{
if (is_numeric($this->input('room_type'))) {
$newRoomType = RoomType::find($this->input('room_type'));
if ($newRoomType) {
return Room::getRoomSettingValidationRule($settingName, $newRoomType);
}
}

return Room::getRoomSettingValidationRule($settingName);
}
}
23 changes: 23 additions & 0 deletions app/Http/Requests/External/RoomTypeIndexRequest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

declare(strict_types=1);

namespace App\Http\Requests\External;

use Illuminate\Contracts\Validation\ValidationRule;
use Illuminate\Foundation\Http\FormRequest;

class RoomTypeIndexRequest extends FormRequest
{
/**
* Get the validation rules that apply to the request.
*
* @return array<string, ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
return [
'filter' => ['nullable', 'string', 'in:own'],
];
}
}
2 changes: 1 addition & 1 deletion app/Http/Requests/UpdateRoomSettingsRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ private function getAccessCodeValidationRule(): array

$rules = $legacy
? ['alpha_num:ascii', 'lowercase', 'size:6', 'bail']
: ['numeric', 'digits:9', 'bail'];
: ['string', 'numeric', 'digits:9', 'bail'];

// Make sure that the given room type id is a number
if (is_numeric($this->input('room_type'))) {
Expand Down
1 change: 1 addition & 0 deletions app/Http/Resources/ConfigResource.php
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ public function toArray($request)
'ldap' => config('ldap.enabled'),
'shibboleth' => config('services.shibboleth.enabled'),
'oidc' => config('services.oidc.enabled'),
'oauth' => config('passport.enabled'),
],
];
}
Expand Down
Loading
Loading