diff --git a/src/Http/Controllers/GuestCardController.php b/src/Http/Controllers/GuestCardController.php index 187841b..a13f5d7 100644 --- a/src/Http/Controllers/GuestCardController.php +++ b/src/Http/Controllers/GuestCardController.php @@ -4,6 +4,7 @@ namespace Dashboard\Unifi\Http\Controllers; use App\Models\Setting; use App\Models\User; +use Illuminate\Http\Request; use Illuminate\Routing\Controller; /** @@ -44,9 +45,35 @@ class GuestCardController extends Controller ]; } - /** Live poll for the card (any logged-in user who can see the card). */ - public function data() + /** The dashboard card this endpoint feeds — must match UnifiServiceProvider. */ + private const CARD_KEY = 'unifi.guest_wifi'; + + /** + * SECURITY: authorize against the card's own visibility. + * + * This was `web,auth` only, and the route comment claimed "card visibility is + * grant-gated by the shell" — but that gate is PRESENTATION only + * (DashboardController decides which cards to render). The endpoint itself was + * unchecked, so any signed-in account — every student and parent included — + * could fetch the live guest Wi-Fi password by requesting the URL directly. + * + * The endpoint now enforces what the comment always claimed: you may poll it iff + * you may see the card. Super admins pass, as everywhere else. Kept as the card + * gate rather than a permission so the widget stays grantable to non-unifi staff, + * which is the point of a home-page card. + */ + public function data(Request $request) { + $user = $request->user(); + abort_unless($user, 403); + + if (! $user->is_super_admin) { + $allowed = \App\Models\DashboardCardGrant::accessibleCardKeysFor($user) + ->contains(self::CARD_KEY); + + abort_unless($allowed, 403); + } + return response()->json(self::payload() ?? ['title' => null]); }