84 lines
2.7 KiB
PHP
84 lines
2.7 KiB
PHP
<?php
|
|
|
|
namespace App\Policies;
|
|
|
|
use App\Models\User;
|
|
use App\Models\VpnPeer;
|
|
|
|
/**
|
|
* Who may see and do what with a VPN access.
|
|
*
|
|
* Ownership is record-level and lives here; permissions describe elevated
|
|
* capabilities (vpn.view.all, vpn.manage.all) and are checked through Gate.
|
|
* The two are kept apart on purpose: seeing an access is not managing it, and
|
|
* neither of them is holding its private key.
|
|
*
|
|
* There is no Gate::before super-admin shortcut in this application, so these
|
|
* rules are the whole story — in particular downloadConfig() cannot be
|
|
* out-voted by a role.
|
|
*/
|
|
class VpnPeerPolicy
|
|
{
|
|
public function viewAny(User $user): bool
|
|
{
|
|
// Every operator may at least reach the page to find their own access.
|
|
return $user->isOperator();
|
|
}
|
|
|
|
public function view(User $user, VpnPeer $peer): bool
|
|
{
|
|
return $this->owns($user, $peer) || $user->can('vpn.view.all');
|
|
}
|
|
|
|
public function create(User $user): bool
|
|
{
|
|
// Not self-service: an access reaches the management network, so issuing
|
|
// one is an administrative act even for oneself.
|
|
return $user->can('vpn.manage.all');
|
|
}
|
|
|
|
/** Rename, reassign, change stored-config settings. */
|
|
public function update(User $user, VpnPeer $peer): bool
|
|
{
|
|
return $user->can('vpn.manage.all');
|
|
}
|
|
|
|
/** Block / unblock. Owners may switch their own access off and on again. */
|
|
public function block(User $user, VpnPeer $peer): bool
|
|
{
|
|
return $user->can('vpn.manage.all') || $this->owns($user, $peer);
|
|
}
|
|
|
|
public function delete(User $user, VpnPeer $peer): bool
|
|
{
|
|
return $user->can('vpn.manage.all') || $this->owns($user, $peer);
|
|
}
|
|
|
|
/**
|
|
* The private half of someone's credential. Owner only — explicitly NOT
|
|
* vpn.view.all and NOT vpn.manage.all: an administrator who needs access
|
|
* revokes this one and issues themselves their own, which keeps the record
|
|
* of who holds what intact.
|
|
*/
|
|
public function downloadConfig(User $user, VpnPeer $peer): bool
|
|
{
|
|
return $this->owns($user, $peer)
|
|
&& $peer->config_secret !== null
|
|
&& ! $peer->trashed();
|
|
}
|
|
|
|
/**
|
|
* isOperator() is part of ownership on purpose: roles can be taken away by
|
|
* other paths than revokeStaff() — a direct role edit, for instance. Losing
|
|
* the console must close these doors by itself, not rely on whoever removed
|
|
* the role also remembering the tunnel.
|
|
*/
|
|
private function owns(User $user, VpnPeer $peer): bool
|
|
{
|
|
return $user->isOperator()
|
|
&& $peer->kind === VpnPeer::KIND_STAFF
|
|
&& $peer->user_id !== null
|
|
&& $peer->user_id === $user->id;
|
|
}
|
|
}
|