NewWe open-sourced 50+ Laravel packages
Custom AI apps, agents and automation — Roundly ConsultingRoundly
All packages
Connections for Laravel

Gate integration

Set register_gate to true to register a Gate hook, so a host app can authorize through connections. Choose when it answers with gate_mode, and whether wildcard grants count with gate_wildcards:

CONNECTIONS_REGISTER_GATE=true
CONNECTIONS_GATE_MODE=after        # recommended — a policy deny always wins
CONNECTIONS_GATE_WILDCARDS=false   # optional — only exact grants answer through the Gate
use Illuminate\Support\Facades\Gate;

$user->can('publish', $team);                    // true when $user has 'publish' on $team
Gate::forUser($user)->allows('publish', $team);  // the same check
Gate::authorize('publish', $team);               // throws AuthorizationException when nothing grants it
  • The ability name is the permission string; the check runs hasPermissionThroughConnection(), so wildcards (unless gate_wildcards is off), the cache and enforce_active_on_check all apply.
  • The hook answers only when the user and the first argument are both Eloquent models implementing Connectable — a guest or a check without a Connectable argument is left to the Gate.
  • It returns true when the connection grants the ability and null otherwise — it never denies on its own.
  • Blade’s @can and the can: route middleware go through the same Gate.
  • It is off by default so installing the package never surprises a host’s own authorization.

Before or after your policies

gate_mode decides where the hook sits relative to your policies and Gate::define() abilities:

  • before (the default) registers a Gate::before hook. A connection that grants the ability allows it before any policy runs — so a stored * overrides a policy that denies, delete included.
  • after registers a Gate::after hook. It answers only when no policy, ability definition or other before hook returned a result; Laravel keeps the first non-null answer, so a deny always wins, however broad the stored grant. A policy that allows still allows without any connection.
// CONNECTIONS_GATE_MODE=after
Gate::policy(Team::class, TeamPolicy::class);   // delete() returns false, update() returns null

$user->connectTo($team, ['*']);

$user->can('delete', $team);   // false — the policy denied, the connection is never asked
$user->can('update', $team);   // true  — no policy method answered, so the connection did

// CONNECTIONS_GATE_MODE=before (the default)
$user->can('delete', $team);   // true  — the stored * is checked first and overrides the deny

Use after. In 2.1 the default stays before so existing apps that rely on a connection grant beating a policy keep working; the next major makes after the default — set gate_mode to before explicitly if you depend on that behaviour. Any value other than before or after throws InvalidConfigurationException naming the key; a blank value is before.

Exact grants only

Set gate_wildcards to false and only a grant naming the exact ability answers through the Gate. A stored * or posts.* then no longer allows every ability when the Gate asks; hasPermissionThroughConnection() and the other direct checks still honour wildcards. It applies in both modes:

// CONNECTIONS_GATE_WILDCARDS=false
$user->connectTo($everything, ['*']);
$user->connectTo($posts, ['posts.*']);
$user->connectTo($exact, ['posts.delete']);

$user->can('delete', $everything);         // false — a wildcard no longer answers through the Gate
$user->can('posts.delete', $posts);        // false
$user->can('posts.delete', $exact);        // true  — the grant names the exact ability

$user->hasPermissionThroughConnection($everything, 'delete');   // true — direct checks still honour wildcards

Inactive connections still count for nothing under enforce_active_on_check, even with an exact grant. A gate_wildcards value that isn’t a boolean throws InvalidConfigurationException naming the key when the Gate asks.

Upgrading to 2.1

With the Gate integration on, a connection holding * used to allow every ability on the connectable — delete included — over a policy that denied it. 2.1.0 adds no migration and changes no default; to close that gap, set gate_mode to after, and gate_wildcards to false if wildcards should never reach the Gate.

Show your open-source love

This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.

More ways to support, including crypto

By donating, you agree to our donation terms.

Want this built into your product?

We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.