From f9c82d0d1f32a0411374a505c711fb63b52c2115 Mon Sep 17 00:00:00 2001 From: isaacclad Date: Fri, 3 Jul 2026 17:56:39 +0000 Subject: [PATCH] Grant panelist role to Events speakers on conferences and webinars. Verify speaker tokens before room-type role resolution so town-hall sessions get panelist access and speaker-panel placement, and skip the waiting room for panelists. Co-authored-by: Cursor --- app/Http/Controllers/Meet/JoinController.php | 12 +++---- app/Models/Room.php | 2 +- tests/Feature/EventsJoinGateTest.php | 33 ++++++++++++++++++++ 3 files changed, 40 insertions(+), 7 deletions(-) diff --git a/app/Http/Controllers/Meet/JoinController.php b/app/Http/Controllers/Meet/JoinController.php index 9a290e0..8c1841f 100644 --- a/app/Http/Controllers/Meet/JoinController.php +++ b/app/Http/Controllers/Meet/JoinController.php @@ -206,14 +206,14 @@ class JoinController extends Controller $role = ($user && $user->ownerRef() === $room->host_user_ref) ? 'host' : 'guest'; - if ($room->isSpace()) { + if ($role !== 'host' && EventsRegistrationSession::isSpeakerVerified($request, $room)) { + $role = 'panelist'; + } elseif ($room->isSpace()) { $role = $this->spaces->resolveJoinRole($room, $user, $role); - } elseif ($room->isConference() && $role !== 'host') { + } elseif ($room->isConference()) { $role = $this->conferences->resolveJoinRole($room, $user, $email, $role); - } elseif ($room->isWebinar() && $role !== 'host') { - if (EventsRegistrationSession::isSpeakerVerified($request, $room)) { - $role = 'panelist'; - } elseif ($room->isEventsLinked()) { + } elseif ($room->isWebinar()) { + if ($room->isEventsLinked()) { $role = 'attendee'; } else { return back()->withErrors([ diff --git a/app/Models/Room.php b/app/Models/Room.php index 999d6a7..7532439 100644 --- a/app/Models/Room.php +++ b/app/Models/Room.php @@ -183,7 +183,7 @@ class Room extends Model return false; } - if ($role === 'host' || ($user && $user->ownerRef() === $this->host_user_ref)) { + if ($role === 'host' || in_array($role, ['co_host', 'panelist'], true) || ($user && $user->ownerRef() === $this->host_user_ref)) { return false; } diff --git a/tests/Feature/EventsJoinGateTest.php b/tests/Feature/EventsJoinGateTest.php index 756fd23..5c96711 100644 --- a/tests/Feature/EventsJoinGateTest.php +++ b/tests/Feature/EventsJoinGateTest.php @@ -192,6 +192,39 @@ class EventsJoinGateTest extends TestCase ]); } + public function test_speaker_token_grants_panelist_role_on_events_linked_conference(): void + { + $room = $this->createEventsLinkedRoom('town_hall', [ + 'settings' => array_merge(config('meet.default_settings'), [ + 'join_before_host' => true, + 'waiting_room' => false, + ]), + ]); + + $session = Session::create([ + 'owner_ref' => $this->user->public_id, + 'room_id' => $room->id, + 'media_room_name' => 'room-'.$room->uuid, + 'status' => 'live', + 'started_at' => now(), + ]); + $room->update(['status' => 'live']); + + $this->get('/r/'.$room->uuid.'?speaker=speaker-token-123') + ->assertRedirect(route('meet.join', $room)); + + $this->post('/r/'.$room->uuid.'/enter', [ + 'display_name' => 'Keynote Speaker', + ])->assertRedirect(route('meet.room', $session)); + + $this->assertDatabaseHas('meet_participants', [ + 'session_id' => $session->id, + 'display_name' => 'Keynote Speaker', + 'email' => 'speaker@example.com', + 'role' => 'panelist', + ]); + } + /** @param array $overrides */ protected function createEventsLinkedRoom(string $type, array $overrides = []): Room {