belongsTo(NavItem::class); } public function grantedBy(): BelongsTo { return $this->belongsTo(User::class, 'granted_by_user_id'); } /** * True iff $user is allowed to access $navItem under this grant model. * Super-admins always pass. * If there are NO grants for the page, falls back to "open" (anyone * who can reach the route can access — same as before grants existed). */ public static function userCanAccess(User $user, NavItem $navItem): bool { if ($user->is_super_admin) return true; $hasGrants = static::where('nav_item_id', $navItem->id)->exists(); if (! $hasGrants) return true; $groupIds = $user->groups()->pluck('groups.id'); return static::where('nav_item_id', $navItem->id) ->where(function ($q) use ($user, $groupIds) { $q->where(function ($u) use ($user) { $u->where('grantee_type', 'user')->where('grantee_id', $user->id); })->orWhere(function ($g) use ($groupIds) { $g->where('grantee_type', 'group')->whereIn('grantee_id', $groupIds); }); }) ->exists(); } }