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(); } private function owns(User $user, VpnPeer $peer): bool { return $peer->kind === VpnPeer::KIND_STAFF && $peer->user_id !== null && $peer->user_id === $user->id; } }