Enforce tenant member permissions
This commit is contained in:
@@ -19,6 +19,7 @@ use App\Models\Tenant;
|
||||
use App\Models\User;
|
||||
use App\Services\EventJoinTokenService;
|
||||
use App\Support\ApiError;
|
||||
use App\Support\TenantMemberPermissions;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
|
||||
@@ -83,6 +84,8 @@ class EventController extends Controller
|
||||
|
||||
public function store(EventStoreRequest $request): JsonResponse
|
||||
{
|
||||
TenantMemberPermissions::ensureTenantPermission($request, 'events:manage');
|
||||
|
||||
$tenant = $request->attributes->get('tenant');
|
||||
if (! $tenant instanceof Tenant) {
|
||||
$tenantId = $request->attributes->get('tenant_id');
|
||||
@@ -383,6 +386,8 @@ class EventController extends Controller
|
||||
);
|
||||
}
|
||||
|
||||
TenantMemberPermissions::ensureEventPermission($request, $event, 'events:manage');
|
||||
|
||||
$validated = $request->validated();
|
||||
|
||||
if (isset($validated['event_date'])) {
|
||||
@@ -586,6 +591,8 @@ class EventController extends Controller
|
||||
);
|
||||
}
|
||||
|
||||
TenantMemberPermissions::ensureEventPermission($request, $event, 'events:manage');
|
||||
|
||||
$event->delete();
|
||||
|
||||
return response()->json([
|
||||
|
||||
@@ -11,6 +11,7 @@ use App\Models\Event;
|
||||
use App\Models\GuestNotification;
|
||||
use App\Models\GuestPolicySetting;
|
||||
use App\Services\GuestNotificationService;
|
||||
use App\Support\TenantMemberPermissions;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
@@ -23,6 +24,7 @@ class EventGuestNotificationController extends Controller
|
||||
public function index(Request $request, Event $event): JsonResponse
|
||||
{
|
||||
$this->assertEventTenant($request, $event);
|
||||
TenantMemberPermissions::ensureEventPermission($request, $event, 'guest-notifications:manage');
|
||||
|
||||
$limit = max(1, min(100, (int) $request->integer('limit', 25)));
|
||||
|
||||
@@ -38,6 +40,7 @@ class EventGuestNotificationController extends Controller
|
||||
public function store(BroadcastGuestNotificationRequest $request, Event $event): JsonResponse
|
||||
{
|
||||
$this->assertEventTenant($request, $event);
|
||||
TenantMemberPermissions::ensureEventPermission($request, $event, 'guest-notifications:manage');
|
||||
|
||||
$data = $request->validated();
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ use App\Http\Resources\Tenant\EventJoinTokenResource;
|
||||
use App\Models\Event;
|
||||
use App\Models\EventJoinToken;
|
||||
use App\Services\EventJoinTokenService;
|
||||
use App\Support\TenantMemberPermissions;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
|
||||
@@ -19,7 +20,7 @@ class EventJoinTokenController extends Controller
|
||||
|
||||
public function index(Request $request, Event $event): AnonymousResourceCollection
|
||||
{
|
||||
$this->authorizeEvent($request, $event);
|
||||
$this->authorizeEvent($request, $event, 'join-tokens:manage');
|
||||
|
||||
$tokens = $event->joinTokens()
|
||||
->orderByDesc('created_at')
|
||||
@@ -30,7 +31,7 @@ class EventJoinTokenController extends Controller
|
||||
|
||||
public function store(Request $request, Event $event): JsonResponse
|
||||
{
|
||||
$this->authorizeEvent($request, $event);
|
||||
$this->authorizeEvent($request, $event, 'join-tokens:manage');
|
||||
|
||||
$validated = $this->validatePayload($request);
|
||||
|
||||
@@ -45,7 +46,7 @@ class EventJoinTokenController extends Controller
|
||||
|
||||
public function update(Request $request, Event $event, EventJoinToken $joinToken): EventJoinTokenResource
|
||||
{
|
||||
$this->authorizeEvent($request, $event);
|
||||
$this->authorizeEvent($request, $event, 'join-tokens:manage');
|
||||
|
||||
if ($joinToken->event_id !== $event->id) {
|
||||
abort(404);
|
||||
@@ -89,7 +90,7 @@ class EventJoinTokenController extends Controller
|
||||
|
||||
public function destroy(Request $request, Event $event, EventJoinToken $joinToken): EventJoinTokenResource
|
||||
{
|
||||
$this->authorizeEvent($request, $event);
|
||||
$this->authorizeEvent($request, $event, 'join-tokens:manage');
|
||||
|
||||
if ($joinToken->event_id !== $event->id) {
|
||||
abort(404);
|
||||
@@ -101,13 +102,17 @@ class EventJoinTokenController extends Controller
|
||||
return new EventJoinTokenResource($token);
|
||||
}
|
||||
|
||||
private function authorizeEvent(Request $request, Event $event): void
|
||||
private function authorizeEvent(Request $request, Event $event, ?string $permission = null): void
|
||||
{
|
||||
$tenantId = $request->attributes->get('tenant_id');
|
||||
|
||||
if ($event->tenant_id !== $tenantId) {
|
||||
abort(404, 'Event not found');
|
||||
}
|
||||
|
||||
if ($permission) {
|
||||
TenantMemberPermissions::ensureEventPermission($request, $event, $permission);
|
||||
}
|
||||
}
|
||||
|
||||
private function validatePayload(Request $request, bool $partial = false): array
|
||||
|
||||
@@ -6,6 +6,7 @@ use App\Http\Controllers\Controller;
|
||||
use App\Models\Event;
|
||||
use App\Models\EventJoinToken;
|
||||
use App\Support\JoinTokenLayoutRegistry;
|
||||
use App\Support\TenantMemberPermissions;
|
||||
use Dompdf\Dompdf;
|
||||
use Dompdf\Options;
|
||||
use Illuminate\Http\Request;
|
||||
@@ -28,6 +29,7 @@ class EventJoinTokenLayoutController extends Controller
|
||||
public function index(Request $request, Event $event, EventJoinToken $joinToken)
|
||||
{
|
||||
$this->ensureBelongsToEvent($event, $joinToken);
|
||||
TenantMemberPermissions::ensureEventPermission($request, $event, 'join-tokens:manage');
|
||||
|
||||
$layouts = JoinTokenLayoutRegistry::toResponse(function (string $layoutId, string $format) use ($event, $joinToken) {
|
||||
return route('api.v1.tenant.events.join-tokens.layouts.download', [
|
||||
@@ -46,6 +48,7 @@ class EventJoinTokenLayoutController extends Controller
|
||||
public function download(Request $request, Event $event, EventJoinToken $joinToken, string $layout, string $format)
|
||||
{
|
||||
$this->ensureBelongsToEvent($event, $joinToken);
|
||||
TenantMemberPermissions::ensureEventPermission($request, $event, 'join-tokens:manage');
|
||||
|
||||
$layoutConfig = JoinTokenLayoutRegistry::find($layout);
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ use App\Models\Event;
|
||||
use App\Models\EventMember;
|
||||
use App\Models\Tenant;
|
||||
use App\Models\User;
|
||||
use App\Support\TenantMemberPermissions;
|
||||
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
@@ -22,6 +23,7 @@ class EventMemberController extends Controller
|
||||
public function index(Request $request, Event $event): JsonResponse
|
||||
{
|
||||
$this->assertEventTenant($request, $event);
|
||||
TenantMemberPermissions::ensureEventPermission($request, $event, 'members:manage');
|
||||
|
||||
/** @var LengthAwarePaginator $members */
|
||||
$members = $event->members()
|
||||
@@ -34,6 +36,7 @@ class EventMemberController extends Controller
|
||||
public function store(EventMemberInviteRequest $request, Event $event): JsonResponse
|
||||
{
|
||||
$this->assertEventTenant($request, $event);
|
||||
TenantMemberPermissions::ensureEventPermission($request, $event, 'members:manage');
|
||||
|
||||
$data = $request->validated();
|
||||
$tenant = $this->resolveTenantFromRequest($request);
|
||||
@@ -92,6 +95,7 @@ class EventMemberController extends Controller
|
||||
public function destroy(Request $request, Event $event, EventMember $member): JsonResponse
|
||||
{
|
||||
$this->assertEventTenant($request, $event);
|
||||
TenantMemberPermissions::ensureEventPermission($request, $event, 'members:manage');
|
||||
|
||||
if ((int) $member->event_id !== (int) $event->id) {
|
||||
throw ValidationException::withMessages([
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace App\Http\Controllers\Api\Tenant;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Event;
|
||||
use App\Support\TenantMemberPermissions;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use SimpleSoftwareIO\QrCode\Facades\QrCode;
|
||||
@@ -13,6 +14,7 @@ class LiveShowLinkController extends Controller
|
||||
public function show(Request $request, Event $event): JsonResponse
|
||||
{
|
||||
$this->authorizeEvent($request, $event);
|
||||
TenantMemberPermissions::ensureEventPermission($request, $event, 'live-show:manage');
|
||||
|
||||
$token = $event->ensureLiveShowToken();
|
||||
|
||||
@@ -24,6 +26,7 @@ class LiveShowLinkController extends Controller
|
||||
public function rotate(Request $request, Event $event): JsonResponse
|
||||
{
|
||||
$this->authorizeEvent($request, $event);
|
||||
TenantMemberPermissions::ensureEventPermission($request, $event, 'live-show:manage');
|
||||
|
||||
$token = $event->rotateLiveShowToken();
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ use App\Http\Resources\Tenant\PhotoResource;
|
||||
use App\Models\Event;
|
||||
use App\Models\Photo;
|
||||
use App\Support\ApiError;
|
||||
use App\Support\TenantMemberPermissions;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
|
||||
@@ -23,6 +24,7 @@ class LiveShowPhotoController extends Controller
|
||||
$event = Event::where('slug', $eventSlug)
|
||||
->where('tenant_id', $tenantId)
|
||||
->firstOrFail();
|
||||
TenantMemberPermissions::ensureEventPermission($request, $event, 'photos:moderate');
|
||||
|
||||
$liveStatus = $request->string('live_status', 'pending')->toString();
|
||||
$perPage = (int) $request->input('per_page', 20);
|
||||
@@ -51,6 +53,7 @@ class LiveShowPhotoController extends Controller
|
||||
$event = Event::where('slug', $eventSlug)
|
||||
->where('tenant_id', $tenantId)
|
||||
->firstOrFail();
|
||||
TenantMemberPermissions::ensureEventPermission($request, $event, 'photos:moderate');
|
||||
|
||||
if ($photo->event_id !== $event->id) {
|
||||
return ApiError::response(
|
||||
@@ -94,6 +97,7 @@ class LiveShowPhotoController extends Controller
|
||||
$event = Event::where('slug', $eventSlug)
|
||||
->where('tenant_id', $tenantId)
|
||||
->firstOrFail();
|
||||
TenantMemberPermissions::ensureEventPermission($request, $event, 'photos:moderate');
|
||||
|
||||
if ($photo->event_id !== $event->id) {
|
||||
return ApiError::response(
|
||||
@@ -146,6 +150,7 @@ class LiveShowPhotoController extends Controller
|
||||
$event = Event::where('slug', $eventSlug)
|
||||
->where('tenant_id', $tenantId)
|
||||
->firstOrFail();
|
||||
TenantMemberPermissions::ensureEventPermission($request, $event, 'photos:moderate');
|
||||
|
||||
if ($photo->event_id !== $event->id) {
|
||||
return ApiError::response(
|
||||
@@ -173,6 +178,7 @@ class LiveShowPhotoController extends Controller
|
||||
$event = Event::where('slug', $eventSlug)
|
||||
->where('tenant_id', $tenantId)
|
||||
->firstOrFail();
|
||||
TenantMemberPermissions::ensureEventPermission($request, $event, 'photos:moderate');
|
||||
|
||||
if ($photo->event_id !== $event->id) {
|
||||
return ApiError::response(
|
||||
|
||||
@@ -14,6 +14,7 @@ use App\Services\Packages\PackageUsageTracker;
|
||||
use App\Services\Storage\EventStorageManager;
|
||||
use App\Support\ApiError;
|
||||
use App\Support\ImageHelper;
|
||||
use App\Support\TenantMemberPermissions;
|
||||
use App\Support\UploadStream;
|
||||
use App\Support\WatermarkConfigResolver;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
@@ -524,15 +525,8 @@ class PhotoController extends Controller
|
||||
'alt_text' => ['sometimes', 'string', 'max:255'],
|
||||
]);
|
||||
|
||||
// Only tenant admins can moderate
|
||||
if (isset($validated['status']) && ! $this->tokenHasScope($request, 'tenant-admin')) {
|
||||
return ApiError::response(
|
||||
'insufficient_scope',
|
||||
'Insufficient Scopes',
|
||||
'You are not allowed to moderate photos for this event.',
|
||||
Response::HTTP_FORBIDDEN,
|
||||
['required_scope' => 'tenant-admin']
|
||||
);
|
||||
if (isset($validated['status'])) {
|
||||
TenantMemberPermissions::ensureEventPermission($request, $event, 'photos:moderate');
|
||||
}
|
||||
|
||||
$photo->update($validated);
|
||||
@@ -634,6 +628,7 @@ class PhotoController extends Controller
|
||||
$event = Event::where('slug', $eventSlug)
|
||||
->where('tenant_id', $tenantId)
|
||||
->firstOrFail();
|
||||
TenantMemberPermissions::ensureEventPermission($request, $event, 'photos:moderate');
|
||||
|
||||
if ($photo->event_id !== $event->id) {
|
||||
return ApiError::response(
|
||||
@@ -657,6 +652,7 @@ class PhotoController extends Controller
|
||||
$event = Event::where('slug', $eventSlug)
|
||||
->where('tenant_id', $tenantId)
|
||||
->firstOrFail();
|
||||
TenantMemberPermissions::ensureEventPermission($request, $event, 'photos:moderate');
|
||||
|
||||
if ($photo->event_id !== $event->id) {
|
||||
return ApiError::response(
|
||||
@@ -680,6 +676,7 @@ class PhotoController extends Controller
|
||||
$event = Event::where('slug', $eventSlug)
|
||||
->where('tenant_id', $tenantId)
|
||||
->firstOrFail();
|
||||
TenantMemberPermissions::ensureEventPermission($request, $event, 'photos:moderate');
|
||||
|
||||
$request->validate([
|
||||
'photo_ids' => 'required|array',
|
||||
@@ -725,6 +722,7 @@ class PhotoController extends Controller
|
||||
$event = Event::where('slug', $eventSlug)
|
||||
->where('tenant_id', $tenantId)
|
||||
->firstOrFail();
|
||||
TenantMemberPermissions::ensureEventPermission($request, $event, 'photos:moderate');
|
||||
|
||||
$request->validate([
|
||||
'photo_ids' => 'required|array',
|
||||
|
||||
@@ -11,6 +11,7 @@ use App\Models\Task;
|
||||
use App\Models\TaskCollection;
|
||||
use App\Models\Tenant;
|
||||
use App\Support\ApiError;
|
||||
use App\Support\TenantMemberPermissions;
|
||||
use App\Support\TenantRequestResolver;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
@@ -66,6 +67,8 @@ class TaskController extends Controller
|
||||
*/
|
||||
public function store(TaskStoreRequest $request): JsonResponse
|
||||
{
|
||||
TenantMemberPermissions::ensureTenantPermission($request, 'tasks:manage');
|
||||
|
||||
$tenant = $this->currentTenant($request);
|
||||
$collectionId = $request->input('collection_id');
|
||||
$collection = $collectionId ? $this->resolveAccessibleCollection($request, $collectionId) : null;
|
||||
@@ -107,6 +110,8 @@ class TaskController extends Controller
|
||||
*/
|
||||
public function update(TaskUpdateRequest $request, Task $task): JsonResponse
|
||||
{
|
||||
TenantMemberPermissions::ensureTenantPermission($request, 'tasks:manage');
|
||||
|
||||
$tenant = $this->currentTenant($request);
|
||||
|
||||
if ($task->tenant_id !== $tenant->id) {
|
||||
@@ -138,6 +143,8 @@ class TaskController extends Controller
|
||||
*/
|
||||
public function destroy(Request $request, Task $task): JsonResponse
|
||||
{
|
||||
TenantMemberPermissions::ensureTenantPermission($request, 'tasks:manage');
|
||||
|
||||
if ($task->tenant_id !== $this->currentTenant($request)->id) {
|
||||
abort(404, 'Task nicht gefunden.');
|
||||
}
|
||||
@@ -154,6 +161,8 @@ class TaskController extends Controller
|
||||
*/
|
||||
public function assignToEvent(Request $request, Task $task, Event $event): JsonResponse
|
||||
{
|
||||
TenantMemberPermissions::ensureEventPermission($request, $event, 'tasks:manage');
|
||||
|
||||
$tenantId = $this->currentTenant($request)->id;
|
||||
|
||||
if (($task->tenant_id && $task->tenant_id !== $tenantId) || $event->tenant_id !== $tenantId) {
|
||||
@@ -176,6 +185,8 @@ class TaskController extends Controller
|
||||
*/
|
||||
public function bulkAssignToEvent(Request $request, Event $event): JsonResponse
|
||||
{
|
||||
TenantMemberPermissions::ensureEventPermission($request, $event, 'tasks:manage');
|
||||
|
||||
$tenantId = $this->currentTenant($request)->id;
|
||||
|
||||
if ($event->tenant_id !== $tenantId) {
|
||||
@@ -230,6 +241,8 @@ class TaskController extends Controller
|
||||
|
||||
public function bulkDetachFromEvent(Request $request, Event $event): JsonResponse
|
||||
{
|
||||
TenantMemberPermissions::ensureEventPermission($request, $event, 'tasks:manage');
|
||||
|
||||
$tenantId = $this->currentTenant($request)->id;
|
||||
|
||||
if ($event->tenant_id !== $tenantId) {
|
||||
@@ -256,6 +269,8 @@ class TaskController extends Controller
|
||||
|
||||
public function reorderForEvent(Request $request, Event $event): JsonResponse
|
||||
{
|
||||
TenantMemberPermissions::ensureEventPermission($request, $event, 'tasks:manage');
|
||||
|
||||
$tenantId = $this->currentTenant($request)->id;
|
||||
|
||||
if ($event->tenant_id !== $tenantId) {
|
||||
|
||||
Reference in New Issue
Block a user