diff --git a/src/Http/Controllers/GuestCardController.php b/src/Http/Controllers/GuestCardController.php index d32ef18..0bd0f58 100644 --- a/src/Http/Controllers/GuestCardController.php +++ b/src/Http/Controllers/GuestCardController.php @@ -17,6 +17,26 @@ use Illuminate\Routing\Controller; */ class GuestCardController extends Controller { + /** + * Is this card set up enough to ever appear? + * + * The three things payload() needs, asked as one question, so the permission + * screens can say "granted, but not configured yet" instead of leaving + * somebody staring at a home page wondering what they got wrong. The + * operator granted this key to two groups in production and saw nothing + * (2026-08-17); the card was simply never switched on. + * + * Note the third clause: last_password is written ONLY by + * unifi:rotate-passwords, so a school that sets a static guest password by + * hand and never rotates has no card and no obvious reason why. + */ + public static function configured(): bool + { + return (bool) Setting::get('unifi.guest_card.enabled') + && trim((string) Setting::get('unifi.guest_card.ssid', '')) !== '' + && filled(Setting::get('unifi.password_rotation.last_password')); + } + /** Payload shared by the card resolver and the poll endpoint. */ public static function payload(): ?array { diff --git a/src/UnifiServiceProvider.php b/src/UnifiServiceProvider.php index f719f4a..ef80f42 100644 --- a/src/UnifiServiceProvider.php +++ b/src/UnifiServiceProvider.php @@ -46,6 +46,10 @@ class UnifiServiceProvider extends ServiceProvider fn (\App\Models\User $user) => \Dashboard\Unifi\Http\Controllers\GuestCardController::resolve($user), 'The guest network name, current password, and a join QR code — updates automatically when the password rotates.', permission: 'unifi.guest_wifi', + // So the permission screens can say "granted, but not switched + // on yet" rather than leaving a grantee staring at a home page + // with nothing new on it. + configured: fn () => \Dashboard\Unifi\Http\Controllers\GuestCardController::configured(), ); } catch (\Throwable) { // Older shell without the card registry — skip.