Wire space listener email invites and restyle Meet index pages.
Deploy Ladill Meet / deploy (push) Successful in 42s
Deploy Ladill Meet / deploy (push) Successful in 42s
Enforce invite-only room access, validate invite emails on create, assign attendee role for listener invitations, and add invite UI on the room show page. Redesign meetings, rooms, conferences, and webinars indexes to match the Events hero, stats cards, and icon list layout. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1214,6 +1214,107 @@ class MeetWebTest extends TestCase
|
||||
]);
|
||||
}
|
||||
|
||||
public function test_space_create_sends_listener_email_invitations(): void
|
||||
{
|
||||
$this->actingAs($this->user)
|
||||
->post('/rooms', [
|
||||
'title' => 'Listener room',
|
||||
'invite_emails' => 'listener@example.com, bad-email',
|
||||
'invite_only' => true,
|
||||
])
|
||||
->assertSessionHasErrors('invite_emails');
|
||||
|
||||
$this->actingAs($this->user)
|
||||
->post('/rooms', [
|
||||
'title' => 'Listener room',
|
||||
'invite_emails' => 'listener@example.com, guest@example.com',
|
||||
'invite_only' => true,
|
||||
])
|
||||
->assertRedirect();
|
||||
|
||||
$room = Room::where('title', 'Listener room')->firstOrFail();
|
||||
|
||||
$this->assertDatabaseHas('meet_invitations', [
|
||||
'room_id' => $room->id,
|
||||
'email' => 'listener@example.com',
|
||||
'role' => 'attendee',
|
||||
'status' => 'pending',
|
||||
]);
|
||||
|
||||
$this->assertDatabaseHas('meet_invitations', [
|
||||
'room_id' => $room->id,
|
||||
'email' => 'guest@example.com',
|
||||
'role' => 'attendee',
|
||||
]);
|
||||
}
|
||||
|
||||
public function test_private_space_denies_uninvited_join(): void
|
||||
{
|
||||
$room = Room::create([
|
||||
'owner_ref' => $this->user->public_id,
|
||||
'organization_id' => $this->organization->id,
|
||||
'host_user_ref' => $this->user->public_id,
|
||||
'title' => 'Private space',
|
||||
'type' => 'space',
|
||||
'status' => 'scheduled',
|
||||
'scheduled_at' => now()->addHour(),
|
||||
'timezone' => 'UTC',
|
||||
'settings' => array_merge(config('meet.default_settings'), [
|
||||
'audio_only' => true,
|
||||
'invite_only' => true,
|
||||
]),
|
||||
]);
|
||||
|
||||
$stranger = User::create([
|
||||
'public_id' => 'stranger-001',
|
||||
'name' => 'Stranger',
|
||||
'email' => 'stranger@example.com',
|
||||
]);
|
||||
|
||||
$this->actingAs($stranger)
|
||||
->get('/r/'.$room->uuid)
|
||||
->assertOk()
|
||||
->assertSee('This room is private');
|
||||
}
|
||||
|
||||
public function test_private_space_allows_invited_email_to_join(): void
|
||||
{
|
||||
$room = Room::create([
|
||||
'owner_ref' => $this->user->public_id,
|
||||
'organization_id' => $this->organization->id,
|
||||
'host_user_ref' => $this->user->public_id,
|
||||
'title' => 'Invited space',
|
||||
'type' => 'space',
|
||||
'status' => 'scheduled',
|
||||
'scheduled_at' => now()->addHour(),
|
||||
'timezone' => 'UTC',
|
||||
'settings' => array_merge(config('meet.default_settings'), [
|
||||
'audio_only' => true,
|
||||
'invite_only' => true,
|
||||
]),
|
||||
]);
|
||||
|
||||
\App\Models\Invitation::create([
|
||||
'owner_ref' => $this->user->public_id,
|
||||
'room_id' => $room->id,
|
||||
'email' => 'invited@example.com',
|
||||
'role' => 'attendee',
|
||||
'status' => 'pending',
|
||||
'rsvp_token' => 'test-token',
|
||||
]);
|
||||
|
||||
$invited = User::create([
|
||||
'public_id' => 'invited-001',
|
||||
'name' => 'Invited Listener',
|
||||
'email' => 'invited@example.com',
|
||||
]);
|
||||
|
||||
$this->actingAs($invited)
|
||||
->get('/r/'.$room->uuid)
|
||||
->assertOk()
|
||||
->assertDontSee('This room is private');
|
||||
}
|
||||
|
||||
public function test_space_host_cannot_create_breakouts(): void
|
||||
{
|
||||
$room = Room::create([
|
||||
|
||||
Reference in New Issue
Block a user