Fix binkp remote closing connection, add/delete session details, menu item this system, minor CSS fixes, move system form editing to individual files

This commit is contained in:
Deon George 2021-07-04 21:47:23 +10:00
parent d56681a187
commit acfde97e79
21 changed files with 1293 additions and 655 deletions

View File

@ -107,6 +107,7 @@ abstract class Protocol
switch ($key) { switch ($key) {
case 'ls_SkipGuard': /* double-skip protection on/off */ case 'ls_SkipGuard': /* double-skip protection on/off */
case 'rxOptions': /* Options from ZRINIT header */ case 'rxOptions': /* Options from ZRINIT header */
case 'socket_error':
return $this->comms[$key] ?? 0; return $this->comms[$key] ?? 0;
case 'ls_rxAttnStr': case 'ls_rxAttnStr':
@ -126,6 +127,7 @@ abstract class Protocol
case 'ls_rxAttnStr': case 'ls_rxAttnStr':
case 'ls_SkipGuard': case 'ls_SkipGuard':
case 'rxOptions': case 'rxOptions':
case 'socket_error':
$this->comms[$key] = $value; $this->comms[$key] = $value;
break; break;

View File

@ -300,8 +300,15 @@ final class SocketClient {
throw new SocketException($x=socket_last_error($this->connection),socket_strerror($x)); throw new SocketException($x=socket_last_error($this->connection),socket_strerror($x));
// If our buffer is null, see if we have any out of band data. // If our buffer is null, see if we have any out of band data.
if (($rc == 0) && is_nulL($buf) && ($this->hasData(0) > 0)) // @todo We throw an errorexception when the socket is closed by the remote I think.
socket_recv($this->connection,$buf, $len,MSG_OOB); if (($rc == 0) && is_nulL($buf) && ($this->hasData(0) > 0)) {
try {
socket_recv($this->connection,$buf, $len,MSG_OOB);
} catch (\Exception $e) {
throw new SocketException($x=socket_last_error($this->connection),socket_strerror($x));
}
}
return is_null($buf) ? '' : $buf; return is_null($buf) ? '' : $buf;
} }

View File

@ -10,6 +10,7 @@ final class SocketException extends \Exception {
public const CANT_CONNECT = 5; public const CANT_CONNECT = 5;
public const SOCKET_ERROR = 6; public const SOCKET_ERROR = 6;
public const SOCKET_EAGAIN = 11; public const SOCKET_EAGAIN = 11;
public const SOCKET_READ = 22;
private array $messages = [ private array $messages = [
self::CANT_CREATE_SOCKET => 'Can\'t create socket: "%s"', self::CANT_CREATE_SOCKET => 'Can\'t create socket: "%s"',
@ -19,6 +20,7 @@ final class SocketException extends \Exception {
self::CANT_CONNECT => 'Can\'t connect: "%s"', self::CANT_CONNECT => 'Can\'t connect: "%s"',
self::SOCKET_ERROR => 'Socket Error: "%s"', self::SOCKET_ERROR => 'Socket Error: "%s"',
self::SOCKET_EAGAIN => 'Socket Resource Temporarily Unavailable - Try again', self::SOCKET_EAGAIN => 'Socket Resource Temporarily Unavailable - Try again',
self::SOCKET_READ => 'Unable to read from socket',
]; ];
public function __construct(int $code,string $params=NULL) { public function __construct(int $code,string $params=NULL) {

View File

@ -4,7 +4,7 @@ namespace App\Http\Controllers;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use App\Models\{Address,System}; use App\Models\{Address,System,Zone};
use App\Rules\{FidoInteger,TwoByteInteger}; use App\Rules\{FidoInteger,TwoByteInteger};
class SystemController extends Controller class SystemController extends Controller
@ -24,6 +24,7 @@ class SystemController extends Controller
*/ */
public function add_address(Request $request,System $o) public function add_address(Request $request,System $o)
{ {
// @todo This should be admin of the zone
$this->authorize('admin',$o); $this->authorize('admin',$o);
session()->flash('add_address',TRUE); session()->flash('add_address',TRUE);
@ -182,6 +183,35 @@ class SystemController extends Controller
return redirect()->to(sprintf('ftn/system/addedit/%d',$o->id)); return redirect()->to(sprintf('ftn/system/addedit/%d',$o->id));
} }
/**
* Add Session details
*
* @param Request $request
* @param System $o
* @return \Illuminate\Http\RedirectResponse
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function add_session(Request $request,System $o)
{
// @todo This should be admin of the zone
$this->authorize('admin',$o);
session()->flash('add_session',TRUE);
$validate = $request->validate([
'zone_id' => 'required|exists:zones,id',
'sespass' => 'required|string|min:4',
'pktpass' => 'required|string|min:4|max:8',
'ticpass' => 'required|string|min:4',
'fixpass' => 'required|string|min:4',
]);
$zo = Zone::findOrFail($validate['zone_id']);
$o->sessions()->attach($zo,$validate);
return redirect()->to(sprintf('ftn/system/addedit/%d',$o->id));
}
/** /**
* Add or edit a node * Add or edit a node
*/ */
@ -225,6 +255,7 @@ class SystemController extends Controller
*/ */
public function del_address(Address $o) public function del_address(Address $o)
{ {
// @todo This should be admin of the zone
$this->authorize('admin',$o); $this->authorize('admin',$o);
session()->flash('add_address',TRUE); session()->flash('add_address',TRUE);
@ -236,6 +267,28 @@ class SystemController extends Controller
return redirect()->to(sprintf('ftn/system/addedit/%d',$sid)); return redirect()->to(sprintf('ftn/system/addedit/%d',$sid));
} }
/**
* Delete address assigned to a host
*
* @param Address $o
* @return \Illuminate\Http\RedirectResponse
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function del_session(System $o,Zone $zo)
{
$this->authorize('admin',$zo);
session()->flash('add_session',TRUE);
$o->sessions()->detach($zo);
return redirect()->to(sprintf('ftn/system/addedit/%d',$o->id));
}
public function ours()
{
return view('system.ours');
}
/** /**
* Suspend address assigned to a host * Suspend address assigned to a host
* *
@ -245,6 +298,7 @@ class SystemController extends Controller
*/ */
public function sus_address(Address $o) public function sus_address(Address $o)
{ {
// @todo This should be admin of the zone
$this->authorize('admin',$o); $this->authorize('admin',$o);
session()->flash('add_address',TRUE); session()->flash('add_address',TRUE);

View File

@ -8,20 +8,20 @@ use Illuminate\Support\Facades\Auth;
class ActiveUser class ActiveUser
{ {
/** /**
* Handle an incoming request. * Handle an incoming request.
* *
* @param \Illuminate\Http\Request $request * @param \Illuminate\Http\Request $request
* @param \Closure $next * @param \Closure $next
* @return mixed * @return mixed
*/ */
public function handle(Request $request, Closure $next) public function handle(Request $request, Closure $next)
{ {
if (Auth::user()->exists && ! Auth::user()->active) { if (Auth::user()->exists && ! Auth::user()->active) {
Auth::logout(); Auth::logout();
abort(403,'Your account is not active'); abort(403,'Your account is not active');
} }
return $next($request); return $next($request);
} }
} }

View File

@ -26,6 +26,12 @@ class Address extends Model
/* RELATIONS */ /* RELATIONS */
/**
* Find children dependant on this record
*
* @todo While this is finding children of hubs, we are not currently finding children of Hosts or Regions.
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function children() public function children()
{ {
return $this->belongsTo(self::class,'id','hub_id'); return $this->belongsTo(self::class,'id','hub_id');
@ -162,7 +168,7 @@ class Address extends Model
static $session = NULL; static $session = NULL;
if (is_null($session)) { if (is_null($session)) {
$session = (new AddressZone) $session = (new SystemZone)
->where('zone_id',$this->zone_id) ->where('zone_id',$this->zone_id)
->where('system_id',$this->system_id) ->where('system_id',$this->system_id)
->single(); ->single();

View File

@ -1,10 +0,0 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class AddressZone extends Model
{
protected $table = 'address_zone';
}

View File

@ -23,6 +23,37 @@ class System extends Model
->orderBy('point_id'); ->orderBy('point_id');
} }
/**
* Session Passwords for system
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function sessions()
{
return $this->belongsToMany(Zone::class)
->withPivot(['sespass','pktpass','ticpass','fixpass','zt_ipv4','zt_ipv6']);
}
/**
* If this system is configured as this host
*
* @return \Illuminate\Database\Eloquent\Relations\HasOne
*/
public function setup()
{
return $this->hasOne(Setup::class);
}
/**
* Zones a system has addresses for
*
* @return \Illuminate\Database\Eloquent\Relations\HasManyThrough
*/
public function zones()
{
return $this->hasManyThrough(Zone::class,Address::class,'system_id','id','id','zone_id');
}
/* GENERAL METHODS */ /* GENERAL METHODS */
/** /**

20
app/Models/SystemZone.php Normal file
View File

@ -0,0 +1,20 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class SystemZone extends Model
{
protected $table = 'system_zone';
public function system()
{
return $this->belongsTo(System::class);
}
public function zone()
{
return $this->belongsTo(Zone::class);
}
}

View File

@ -18,6 +18,7 @@
"repat/laravel-job-models": "^0.5.1" "repat/laravel-job-models": "^0.5.1"
}, },
"require-dev": { "require-dev": {
"barryvdh/laravel-debugbar": "^3.6",
"barryvdh/laravel-ide-helper": "^2.10", "barryvdh/laravel-ide-helper": "^2.10",
"facade/ignition": "^2.5", "facade/ignition": "^2.5",
"fakerphp/faker": "^1.9.1", "fakerphp/faker": "^1.9.1",

221
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "375895896140ab8b282d257a18cc4a6d", "content-hash": "cc549eaf378b58b95b4c809dd45553db",
"packages": [ "packages": [
{ {
"name": "asm89/stack-cors", "name": "asm89/stack-cors",
@ -5725,6 +5725,91 @@
} }
], ],
"packages-dev": [ "packages-dev": [
{
"name": "barryvdh/laravel-debugbar",
"version": "v3.6.2",
"source": {
"type": "git",
"url": "https://github.com/barryvdh/laravel-debugbar.git",
"reference": "70b89754913fd89fef16d0170a91dbc2a5cd633a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/70b89754913fd89fef16d0170a91dbc2a5cd633a",
"reference": "70b89754913fd89fef16d0170a91dbc2a5cd633a",
"shasum": ""
},
"require": {
"illuminate/routing": "^6|^7|^8",
"illuminate/session": "^6|^7|^8",
"illuminate/support": "^6|^7|^8",
"maximebf/debugbar": "^1.16.3",
"php": ">=7.2",
"symfony/debug": "^4.3|^5",
"symfony/finder": "^4.3|^5"
},
"require-dev": {
"mockery/mockery": "^1.3.3",
"orchestra/testbench-dusk": "^4|^5|^6",
"phpunit/phpunit": "^8.5|^9.0",
"squizlabs/php_codesniffer": "^3.5"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.5-dev"
},
"laravel": {
"providers": [
"Barryvdh\\Debugbar\\ServiceProvider"
],
"aliases": {
"Debugbar": "Barryvdh\\Debugbar\\Facade"
}
}
},
"autoload": {
"psr-4": {
"Barryvdh\\Debugbar\\": "src/"
},
"files": [
"src/helpers.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Barry vd. Heuvel",
"email": "barryvdh@gmail.com"
}
],
"description": "PHP Debugbar integration for Laravel",
"keywords": [
"debug",
"debugbar",
"laravel",
"profiler",
"webprofiler"
],
"support": {
"issues": "https://github.com/barryvdh/laravel-debugbar/issues",
"source": "https://github.com/barryvdh/laravel-debugbar/tree/v3.6.2"
},
"funding": [
{
"url": "https://fruitcake.nl",
"type": "custom"
},
{
"url": "https://github.com/barryvdh",
"type": "github"
}
],
"time": "2021-06-14T14:29:26+00:00"
},
{ {
"name": "barryvdh/laravel-ide-helper", "name": "barryvdh/laravel-ide-helper",
"version": "v2.10.0", "version": "v2.10.0",
@ -7199,6 +7284,71 @@
}, },
"time": "2020-05-27T16:41:55+00:00" "time": "2020-05-27T16:41:55+00:00"
}, },
{
"name": "maximebf/debugbar",
"version": "v1.16.5",
"source": {
"type": "git",
"url": "https://github.com/maximebf/php-debugbar.git",
"reference": "6d51ee9e94cff14412783785e79a4e7ef97b9d62"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/maximebf/php-debugbar/zipball/6d51ee9e94cff14412783785e79a4e7ef97b9d62",
"reference": "6d51ee9e94cff14412783785e79a4e7ef97b9d62",
"shasum": ""
},
"require": {
"php": "^7.1|^8",
"psr/log": "^1.0",
"symfony/var-dumper": "^2.6|^3|^4|^5"
},
"require-dev": {
"phpunit/phpunit": "^7.5.20 || ^9.4.2"
},
"suggest": {
"kriswallsmith/assetic": "The best way to manage assets",
"monolog/monolog": "Log using Monolog",
"predis/predis": "Redis storage"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.16-dev"
}
},
"autoload": {
"psr-4": {
"DebugBar\\": "src/DebugBar/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Maxime Bouroumeau-Fuseau",
"email": "maxime.bouroumeau@gmail.com",
"homepage": "http://maximebf.com"
},
{
"name": "Barry vd. Heuvel",
"email": "barryvdh@gmail.com"
}
],
"description": "Debug bar in the browser for php application",
"homepage": "https://github.com/maximebf/php-debugbar",
"keywords": [
"debug",
"debugbar"
],
"support": {
"issues": "https://github.com/maximebf/php-debugbar/issues",
"source": "https://github.com/maximebf/php-debugbar/tree/v1.16.5"
},
"time": "2020-12-07T11:07:24+00:00"
},
{ {
"name": "mockery/mockery", "name": "mockery/mockery",
"version": "1.4.3", "version": "1.4.3",
@ -9268,6 +9418,75 @@
}, },
"time": "2020-07-07T18:42:57+00:00" "time": "2020-07-07T18:42:57+00:00"
}, },
{
"name": "symfony/debug",
"version": "v4.4.25",
"source": {
"type": "git",
"url": "https://github.com/symfony/debug.git",
"reference": "a8d2d5c94438548bff9f998ca874e202bb29d07f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/debug/zipball/a8d2d5c94438548bff9f998ca874e202bb29d07f",
"reference": "a8d2d5c94438548bff9f998ca874e202bb29d07f",
"shasum": ""
},
"require": {
"php": ">=7.1.3",
"psr/log": "~1.0",
"symfony/polyfill-php80": "^1.15"
},
"conflict": {
"symfony/http-kernel": "<3.4"
},
"require-dev": {
"symfony/http-kernel": "^3.4|^4.0|^5.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Symfony\\Component\\Debug\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Provides tools to ease debugging PHP code",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/debug/tree/v4.4.25"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2021-05-26T17:39:37+00:00"
},
{ {
"name": "symfony/filesystem", "name": "symfony/filesystem",
"version": "v5.3.0", "version": "v5.3.0",

View File

@ -0,0 +1,28 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class SessionPasswords extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
DB::statement('ALTER TABLE address_zone RENAME TO system_zone');
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
DB::statement('ALTER TABLE system_zone RENAME TO address_zone');
}
}

View File

@ -594,12 +594,20 @@ tbody {
margin-bottom:.5em margin-bottom:.5em
} }
.monotable thead { .monotable thead {
color:#fff;
background-color:#000
}
.monotable thead tr:first-child {
border-top:1px solid #666; border-top:1px solid #666;
border-left:2px solid #666; border-left:2px solid #666;
border-right:2px solid #666; border-right:2px solid #666;
border-bottom:0; border-bottom:1px solid #666;
color:#fff; }
background-color:#000 .monotable thead tr {
border-top:1px solid #666;
border-left:2px solid #666;
border-right:2px solid #666;
border-bottom: 0;
} }
.monotable th { .monotable th {
padding:.5em 1.5ch .4em; padding:.5em 1.5ch .4em;

View File

@ -159,14 +159,6 @@
order: [ order: [
[3,'asc'], [3,'asc'],
], ],
/*
columnDefs: [
{
targets: [5,6],
visible: false,
}
],
*/
}); });
</script> </script>
@append @append

View File

@ -8,6 +8,11 @@
<dd><a href="{{ url('ftn/zone') }}" >Zones</a></dd> <dd><a href="{{ url('ftn/zone') }}" >Zones</a></dd>
</dl> </dl>
<dl>
<dt>System Admin</dt>
<dd><a href="{{ url('ftn/our_systems') }}">This Host Systems</a></dd>
</dl>
@can('admin') @can('admin')
<dl> <dl>
<dt>Users</dt> <dt>Users</dt>
@ -16,6 +21,7 @@
</dl> </dl>
@endcan @endcan
@endauth @endauth
<dl> <dl>
<dt>Expore Networks</dt> <dt>Expore Networks</dt>
@foreach (\App\Models\Domain::active() @foreach (\App\Models\Domain::active()

View File

@ -1,7 +1,3 @@
@php
use App\Models\Setup;
@endphp
@extends('layouts.app') @extends('layouts.app')
@section('htmlheader_title') @section('htmlheader_title')
@ -10,213 +6,75 @@
@section('content') @section('content')
@if ($o->exists) @if ($o->exists)
<h1>{{ $o->name }}</h1> <h1>{{ $o->name }}@if($o->setup) <sup style="text-shadow: 0 0; font-size: 50%; top: -1em;">*</sup>@endif</h1>
@if($o->setup)<sup style="float:right;top:-2em;">* This Host</sup>@endif
@endif @endif
<div class="accordion accordion-flush" id="accordion_homepage"> <div class="accordion accordion-flush" id="accordion_homepage">
@if ($o->exists) @if ($o->exists)
<!-- System --> <!-- System -->
<div class="accordion-item"> <div class="accordion-item">
<h3 class="accordion-header" id="system" data-bs-toggle="collapse" data-bs-target="#collapse_system" aria-expanded="true" aria-controls="collapse_system">System</h3> <h3 class="accordion-header" id="system" data-bs-toggle="collapse" data-bs-target="#collapse_system" aria-expanded="true" aria-controls="collapse_system">System</h3>
<div id="collapse_system" class="accordion-collapse collapse {{ ! session()->has('add_address') ? 'show' : '' }}" aria-labelledby="system" data-bs-parent="#accordion_homepage"> <div id="collapse_system" class="accordion-collapse collapse {{ ((! session()->has('add_address')) && (! session()->has('add_session'))) ? 'show' : '' }}" aria-labelledby="system" data-bs-parent="#accordion_homepage">
<div class="accordion-body"> <div class="accordion-body">
@endif @include('system.form-system')
<form class="row g-0 needs-validation" method="post" novalidate>
@csrf
<div class="row">
<div class="col-12">
<div class="greyframe titledbox shadow0xb0">
<h2 class="cap">@if($o->exists) Update @else Add @endif System</h2>
<div class="row">
<div class="col-4">
<label for="name" class="form-label">Name</label>
<div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-tag-fill"></i></span>
<input type="text" class="form-control @error('name') is-invalid @enderror" id="name" placeholder="Name" name="name" value="{{ old('name',$o->name) }}" required @cannot('admin',$o)disabled @endcannot autofocus>
<span class="invalid-feedback" role="alert">
@error('name')
{{ $message }}
@else
A name is required.
@enderror
</span>
</div>
</div>
<div class="col-2">
<label for="active" class="form-label">Active</label>
<div class="input-group">
<div class="btn-group" role="group">
<input type="radio" class="btn-check" name="active" id="active_yes" value="1" required @cannot('admin',$o)disabled @endcannot @if(old('active',$o->active))checked @endif>
<label class="btn btn-outline-success" for="active_yes">Yes</label>
<input type="radio" class="btn-check btn-danger" name="active" id="active_no" value="0" required @cannot('admin',$o)disabled @endcannot @if(! old('active',$o->active))checked @endif>
<label class="btn btn-outline-danger" for="active_no">No</label>
</div>
</div>
</div>
<div class="col-3">
<label for="zt_id" class="form-label">ZeroTier ID</label>
<div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-shield-lock-fill"></i></span>
<input type="text" class="form-control @error('zt_id') is-invalid @enderror" id="zt_id" placeholder="ZeroTier" name="zt_id" value="{{ old('zt_id',$o->zt_id) }}" @cannot('admin',$o)disabled @endcannot>
<span class="invalid-feedback" role="alert">
@error('zt_id')
{{ $message }}
@enderror
</span>
</div>
</div>
</div>
<div class="row">
<div class="col-4">
<label for="sysop" class="form-label">Sysop</label>
<div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-globe"></i></span>
<input type="text" class="form-control @error('sysop') is-invalid @enderror" id="sysop" placeholder="Sysop" name="sysop" value="{{ old('sysop',$o->sysop) }}" required @cannot('admin',$o)disabled @endcannot autocomplete="name">
<span class="invalid-feedback" role="alert">
@error('sysop')
{{ $message }}
@else
A Sysop's name is required.
@enderror
</span>
</div>
</div>
<div class="col-8">
<label for="location" class="form-label">Location</label>
<div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-globe"></i></span>
<input type="text" class="form-control @error('location') is-invalid @enderror" id="location" placeholder="Location" name="location" value="{{ old('location',$o->location) }}" required @cannot('admin',$o)disabled @endcannot>
<span class="invalid-feedback" role="alert">
@error('location')
{{ $message }}
@else
System location is required.
@enderror
</span>
</div>
</div>
</div>
<div class="row">
<div class="col-12">
<h4>Mailer Details</h4>
<div class="pt-0 row">
<div class="col-4">
<label for="method" class="form-label">Connection Method</label>
<div class="input-group">
<span class="input-group-text"><i class="bi bi-wifi"></i></span>
<select class="form-select @error('method') is-invalid @enderror" id="mailer_type" name="mailer_type" @cannot('admin',$o)disabled @endcannot>
<option></option>
<option value="{{ Setup::O_BINKP }}" @if(old('mailer_type',$o->mailer_type) == Setup::O_BINKP)selected @endif)}}>BINKP</option>
<option value="{{ Setup::O_EMSI }}" @if(old('mailer_type',$o->mailer_type) == Setup::O_EMSI)selected @endif)}}>EMSI</option>
</select>
</div>
</div>
<div class="col-8">
<label for="address" class="form-label">Address</label>
<div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-globe"></i></span>
<input type="text" class="w-75 form-control @error('mailer_address') is-invalid @enderror" id="mailer_address" placeholder="FQDN" name="mailer_address" value="{{ old('mailer_address',$o->mailer_address) }}" @cannot('admin',$o)disabled @endcannot>
<input type="text" class="form-control @error('mailer_port') is-invalid @enderror" id="mailer_port" placeholder="Port" name="mailer_port" value="{{ old('mailer_port',$o->mailer_port) }}" @cannot('admin',$o)disabled @endcannot>
<span class="invalid-feedback" role="alert">
@error('mailer_address')
{{ $message }}
@enderror
@error('mailer_port')
{{ $message }}
@enderror
</span>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-12">
<h4>BBS Details</h4>
<div class="pt-0 row">
<div class="col-4">
<label for="method" class="form-label">Connection Method</label>
<div class="input-group">
<span class="input-group-text"><i class="bi bi-wifi"></i></span>
<select class="form-select @error('method') is-invalid @enderror" id="method" name="method" @cannot('admin',$o)disabled @endcannot>
<option></option>
<option value="23" @if(old('method',$o->method) == 23)selected @endif)}}>Telnet</option>
<option value="22" @if(old('method',$o->method) == 22)selected @endif)}}>SSH</option>
<option value="519" @if(old('method',$o->method) == 519)selected @endif)}}>Rlogin</option>
</select>
</div>
</div>
<div class="col-8">
<label for="address" class="form-label">Address</label>
<div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-globe"></i></span>
<input type="text" class="w-75 form-control @error('address') is-invalid @enderror" id="address" placeholder="FQDN" name="address" value="{{ old('address',$o->address) }}" @cannot('admin',$o)disabled @endcannot>
<input type="text" class="form-control @error('port') is-invalid @enderror" id="port" placeholder="Port" name="port" value="{{ old('port',$o->port) }}" @cannot('admin',$o)disabled @endcannot>
<span class="invalid-feedback" role="alert">
@error('address')
{{ $message }}
@enderror
@error('port')
{{ $message }}
@enderror
</span>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-12">
<label for="notes" class="form-label">Notes</label>
<textarea class="form-control" rows=3 name="notes" placeholder="Notes..." @cannot('admin',$o)disabled @endcannot>{{ old('notes',$o->notes) }}</textarea>
</div>
</div>
<div class="row">
<div class="col-12">
<a href="{{ url('ftn/system') }}" class="btn btn-danger">Cancel</a>
@can('admin',$o)
<button type="submit" name="submit" class="btn btn-success mr-0 float-end">@if ($o->exists)Save @else Add @endif</button>
@endcan
</div>
</div>
</div>
</div>
</div>
</form>
@if ($o->exists)
</div> </div>
</div> </div>
</div> </div>
@endif
@if($o->exists) @if(! $o->setup)
<!-- Authentication --> <!-- Authentication -->
<div class="accordion-item"> <div class="accordion-item">
<h3 class="accordion-header" id="authentication" data-bs-toggle="collapse" data-bs-target="#collapse_auth" aria-expanded="false" aria-controls="collapse_auth">System Authentication</h3> <h3 class="accordion-header" id="authentication" data-bs-toggle="collapse" data-bs-target="#collapse_auth" aria-expanded="false" aria-controls="collapse_auth">System Authentication</h3>
<div id="collapse_auth" class="accordion-collapse collapse" aria-labelledby="authentication" data-bs-parent="#accordion_homepage"> <div id="collapse_auth" class="accordion-collapse collapse {{ session()->has('add_session') ? 'show' : '' }}" aria-labelledby="authentication" data-bs-parent="#accordion_homepage">
<div class="accordion-body"> <div class="accordion-body">
TBA @if ($o->sessions->count())
<table class="table monotable">
<thead>
<tr>
<th>&nbsp;</th>
<th colspan="4" class="text-center">Passwords</th>
<th>&nbsp;</th>
</tr>
<tr>
<th>Zone</th>
<th>Session</th>
<th>Packet</th>
<th>TIC</th>
<th>Areafix</th>
<th>&nbsp;</th>
</tr>
</thead>
<tbody>
@foreach ($o->sessions->sortBy('zone_id') as $oo)
<tr>
<td>{{ $oo->zone_id }}<span>@</span>{{ $oo->domain->name }}</td>
<td>{{ $oo->pivot->sespass }}</td>
<td>{{ $oo->pivot->pktpass }}</td>
<td>{{ $oo->pivot->ticpass }}</td>
<td>{{ $oo->pivot->fixpass }}</td>
<td style="width: 70px;">
{{--
<a href="{{ url('ftn/system/modsession',[$oo->id]) }}" title="Modify Details" class="modify"><i class="bi bi-pen-fill"></i></a>
--}}
<a href="{{ url('ftn/system/delsession',[$o->id,$oo->id]) }}" title="Delete Details" class="delete"><i class="bi bi-trash-fill"></i></a>
</td>
</tr>
@endforeach
</tbody>
</table>
@else
<p>No session details exist</p>
@endif
@include('system.form-session')
</div>
</div> </div>
</div> </div>
</div> @endif
<!-- Addresses --> <!-- Addresses -->
<div class="accordion-item"> <div class="accordion-item">
@ -319,431 +177,18 @@
@endif @endif
@can('admin',$o) @can('admin',$o)
<form class="row g-0 needs-validation" method="post" action="{{ url('ftn/system/addaddress',$o->id) }}" novalidate> @include('system.form-address')
<input type="hidden" id="action" name="action" value="">
@csrf
<div class="row pt-0">
<div class="col-12">
<div class="greyframe titledbox shadow0xb0">
<h2 class="cap">Assign New address</h2>
<div class="row">
<!-- Select Zone -->
<div class="col-3">
<label for="zone_id" class="form-label">Zone</label>
<div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-hash"></i></span>
<select class="form-select @error('zone_id') is-invalid @enderror" id="zone_id" name="zone_id" required>
<option></option>
@foreach(\App\Models\Zone::active()->domainZoneOrder()->with(['domain'])->get() as $zo)
<option value="{{ $zo->id }}">{{ $zo->zone_id }} <small>({{ $zo->domain->name }})</small></option>
@endforeach
</select>
<span class="invalid-feedback" role="alert">
@error('zone_id')
{{ $message }}
@else
Please select the Zone for the node's address.
@enderror
</span>
</div>
</div>
<!-- Select Region -->
<div class="col-3 d-none" id="region-select">
<label for="region_id" class="form-label">Region</label>
<div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-geo"></i></span>
<select class="form-select @error('region_id') is-invalid @enderror" id="region_id" name="region_id" required>
</select>
<span class="invalid-feedback" role="alert">
@error('region_id')
{{ $message }}
@else
Please make a choice.
@enderror
</span>
</div>
</div>
<!-- Select Host -->
<div class="col-3 d-none" id="host-select">
<label for="host_id" class="form-label">Host</label>
<div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-diagram-3-fill"></i></span>
<select class="form-select @error('host_id') is-invalid @enderror" id="host_id" name="host_id">
</select>
<span class="invalid-feedback" role="alert">
@error('host_id')
{{ $message }}
@enderror
</span>
</div>
</div>
<!-- Select Hub -->
<div class="col-3 d-none" id="hub-select">
<label for="hub_id" class="form-label">Hub</label>
<div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-diagram-2-fill"></i></span>
<select class="form-select @error('hub_id') is-invalid @enderror" id="hub_id" name="hub_id">
</select>
<span class="invalid-feedback" role="alert">
@error('hub_id')
{{ $message }}
@enderror
</span>
</div>
</div>
</div>
<div class="row">
<!-- Node/Point address -->
<div class="col-3 d-none" id="node-address">
<label for="node_id" class="form-label">Node/Point Address</label>
<div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-hash"></i></span>
<input type="text" style="width: 35%;" class="form-control @error('node_id') is-invalid @enderror" id="node_id" placeholder="Node" name="node_id" value="{{ old('node_id',$o->node_id) }}" @cannot('admin',$o)disabled @endcannot>
<span class="input-group-text ml-1 mr-1 p-0">.</span>
<input type="text" class="form-control @error('point_id') is-invalid @enderror" id="point_id" placeholder="0" name="point_id" value="{{ old('point_id',$o->point_id) ?: 0 }}" @cannot('admin',$o)disabled @endcannot style="padding-left: 0;">
<span class="invalid-feedback" role="alert">
@error('node_id')
{{ $message }}
@enderror
@error('point_id')
{{ $message }}
@enderror
</span>
</div>
</div>
<!-- Region Address -->
<div class="pl-0 col-3 d-none" id="region-address" >
<label for="region" class="form-label">Region Address</label>
<div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-hash"></i></span>
<input type="text" style="width: 35%;" class="form-control @error('region_id_new') is-invalid @enderror" id="region_id_new" placeholder="Region #" name="region_id_new" value="{{ old('region_id_new') }}" @cannot('admin',$o)disabled @endcannot>
<span class="input-group-text">/0.0</span>
<span class="invalid-feedback" role="alert">
@error('region_id_new')
{{ $message }}
@else
The region number is required.
@enderror
</span>
</div>
</div>
<!-- Host Address -->
<div class="pl-0 col-3 d-none" id="host-address">
<label for="host" class="form-label">Host Address</label>
<div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-hash"></i></span>
<input type="text" class="form-control @error('host_id_new') is-invalid @enderror" id="host_id_new" placeholder="Host #" name="host_id_new" value="{{ old('host_id_new') }}" @cannot('admin',$o)disabled @endcannot>
<span class="input-group-text ml-1 mr-1 p-0">/</span>
<input type="text" class="form-control @error('node_id_new') is-invalid @enderror" id="node_id_new" placeholder="Node #" name="node_id_new" value="{{ old('node_id_new') }}" @cannot('admin',$o)disabled @endcannot>
<span class="input-group-text">.0</span>
<span class="invalid-feedback" role="alert">
@error('host_id_new')
{{ $message }}
@else
The host address is required.
@enderror
@error('node_id_new')
{{ $message }}
@else
The node address is required.
@enderror
</span>
</div>
</div>
<!-- Hub Checkbox -->
<div class="col-2 d-none" id="hub-checkbox">
<label for="hub" class="form-label">Hub</label>
<div class="input-group">
<div class="btn-group" role="group">
<input type="radio" class="btn-check" name="hub" id="hub_yes" value="1" required @cannot('admin',$o)disabled @endcannot @if(old('hub',$o->hub))checked @endif>
<label class="btn btn-outline-success" for="hub_yes">Yes</label>
<input type="radio" class="btn-check btn-danger" name="hub" id="hub_no" value="0" required @cannot('admin',$o)disabled @endcannot @if(! old('hub',$o->hub))checked @endif>
<label class="btn btn-outline-danger" for="hub_no">No</label>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-2">
<a href="{{ url('ftn/system') }}" class="btn btn-danger">Cancel</a>
</div>
<span class="col-6 mt-auto mx-auto text-center align-bottom">
@if($errors->count())
<span class="pl-5 btn btn-sm btn-danger" role="alert">
There were errors with the submission.
</span>
@endif
</span>
@can('admin',$o)
<div class="col-2">
<button type="submit" name="submit" class="btn btn-success mr-0 float-end">Add</button>
</div>
@endcan
</div>
</div>
</div>
</div>
</form>
@else @else
This system does not currently belong to any Fido networks. You'll need to ask an admin to assign addresses. This system does not currently belong to any Fido networks. You'll need to ask an admin to assign addresses.
@endcan @endcan
</div> </div>
</div> </div>
</div> </div>
@else
@include('system.form-system')
@endif @endif
</div> </div>
@include('widgets.modal_delete') @include('widgets.modal_delete')
@endsection @endsection
@section('page-scripts')
<script type="text/javascript">
$(document).ready(function() {
/*
// Disable enter for form submission.
$('input').on('keydown', function(event) {
var x = event.which;
if (x === 13) {
event.preventDefault();
}
});
*/
$('#zone_id').on('change',function() {
$(this).parent().find('i').addClass('spinner-grow spinner-grow-sm');
$('#region_id').prop('disabled',true);
$('#region_id').children().remove();
if (! $('#region-address').hasClass('d-none'))
$('#region-address').addClass('d-none');
if (! $('#host-address').hasClass('d-none'))
$('#host-address').addClass('d-none');
if (! $('#host-select').hasClass('d-none'))
$('#host-select').addClass('d-none');
if (! $('#hub-select').hasClass('d-none'))
$('#hub-select').addClass('d-none')
if (! $('#hub-checkbox').hasClass('d-none'))
$('#hub-checkbox').addClass('d-none');
if (! $('#node-address').hasClass('d-none'))
$('#node-address').addClass('d-none');
$.get('{{ url('api/regions') }}'+'/'+this.value,function(data) {
$('#region_id').append('<option value=""></option>');
$('#region_id').append('<option value="0">No Region</option>');
$('#region_id').append('<option value="new">New Region</option>');
data.forEach(function(item) {
$('#region_id').append('<option value="'+item.id+'">'+item.value+'</option>');
});
$('#region_id').prop('disabled',false);
$('#region_id').show();
});
$('#region-select').removeClass('d-none');
$(this).parent().find('i').removeClass('spinner-grow spinner-grow-sm');
});
$('#region_id').on('change',function() {
switch(this.value) {
case '':
if (! $('#region-address').hasClass('d-none'))
$('#region-address').addClass('d-none');
if (! $('#host-select').hasClass('d-none'))
$('#host-select').addClass('d-none');
if (! $('#host-address').hasClass('d-none'))
$('#host-address').addClass('d-none');
if (! $('#hub-select').hasClass('d-none'))
$('#hub-select').addClass('d-none');
if (! $('#hub-checkbox').hasClass('d-none'))
$('#hub-checkbox').addClass('d-none');
if (! $('#node-address').hasClass('d-none'))
$('#node-address').addClass('d-none');
break;
case 'new':
if (! $('#host-select').hasClass('d-none'))
$('#host-select').addClass('d-none');
if (! $('#host-address').hasClass('d-none'))
$('#host-address').addClass('d-none');
if ($('#region-address').hasClass('d-none'))
$('#region-address').removeClass('d-none');
if (! $('#hub-select').hasClass('d-none'))
$('#hub-select').addClass('d-none');
if (! $('#hub-checkbox').hasClass('d-none'))
$('#hub-checkbox').addClass('d-none');
if (! $('#node-address').hasClass('d-none'))
$('#node-address').addClass('d-none');
$('#action').val('region');
break;
case '0':
default:
// Find Hosts
if ($('#host-select').hasClass('d-none'))
$('#host-select').removeClass('d-none');
if (! $('#region-address').hasClass('d-none'))
$('#region-address').addClass('d-none');
if (! $('#hub-select').hasClass('d-none'))
$('#hub-select').addClass('d-none');
if (! $('#hub-checkbox').hasClass('d-none'))
$('#hub-checkbox').addClass('d-none');
if (! $('#host-address').hasClass('d-none'))
$('#host-address').addClass('d-none');
if (! $('#node-address').hasClass('d-none'))
$('#node-address').addClass('d-none');
$(this).parent().find('i').addClass('spinner-grow spinner-grow-sm');
$('#host_id').prop('disabled',true);
$('#host_id').children().remove();
var that = this;
$.get('{{ url('api/hosts') }}'+'/'+$('#zone_id').val()+'/'+this.value,function(data) {
$('#host_id').append('<option value=""></option>');
if (that.value !== '0')
$('#host_id').append('<option value="0">No Host</option>');
$('#host_id').append('<option value="new">New Host</option>');
data.forEach(function(item) {
$('#host_id').append('<option value="'+item.id+'">'+item.value+'</option>');
});
$('#host_id').prop('disabled',false);
$('#host_id').show();
});
$('#host-select').removeClass('d-none');
$(this).parent().find('i').removeClass('spinner-grow spinner-grow-sm');
}
});
$('#host_id').on('change',function() {
switch(this.value) {
case '':
if (! $('#host-address').hasClass('d-none'))
$('#host-address').addClass('d-none');
if (! $('#hub-select').hasClass('d-none'))
$('#hub-select').addClass('d-none');
if (! $('#hub-checkbox').hasClass('d-none'))
$('#hub-checkbox').addClass('d-none');
if (! $('#node-address').hasClass('d-none'))
$('#node-address').addClass('d-none');
break;
case 'new':
if ($('#host-address').hasClass('d-none'))
$('#host-address').removeClass('d-none');
if (! $('#hub-select').hasClass('d-none'))
$('#hub-select').addClass('d-none');
if (! $('#hub-checkbox').hasClass('d-none'))
$('#hub-checkbox').addClass('d-none');
if (! $('#node-address').hasClass('d-none'))
$('#node-address').addClass('d-none');
$('#action').val('host');
break;
case '0':
default:
if (! $('#host-address').hasClass('d-none'))
$('#host-address').addClass('d-none');
if ($('#hub-select').hasClass('d-none'))
$('#hub-select').removeClass('d-none');
if ($('#hub-checkbox').hasClass('d-none'))
$('#hub-checkbox').removeClass('d-none');
if ($('#node-address').hasClass('d-none'))
$('#node-address').removeClass('d-none');
$(this).parent().find('i').addClass('spinner-grow spinner-grow-sm');
$('#hub_id').prop('disabled',true);
$('#hub_id').children().remove();
$.get('{{ url('api/hubs') }}'+'/'+$('#zone_id').val()+'/'+this.value,function(data) {
$('#hub_id').append('<option value="">No Hub</option>');
data.forEach(function(item) {
$('#hub_id').append('<option value="'+item.id+'">'+item.value+'</option>');
});
$('#hub_id').prop('disabled',false);
$('#hub_id').show();
});
$('#hub-select').removeClass('d-none');
$(this).parent().find('i').removeClass('spinner-grow spinner-grow-sm');
$('#action').val('node');
}
});
$('#hub_id').on('change',function() {
switch(this.value) {
case '':
if ($('#hub-checkbox').hasClass('d-none'))
$('#hub-checkbox').removeClass('d-none');
break;
default:
if (! $('#hub-checkbox').hasClass('d-none'))
$('#hub-checkbox').addClass('d-none');
}
});
$('#point_id').on('change',function() {
switch(this.value) {
case '0':
if ($('#hub-checkbox').hasClass('d-none'))
$('#hub-checkbox').removeClass('d-none');
break;
default:
if (! $('#hub-checkbox').hasClass('d-none'))
$('#hub-checkbox').addClass('d-none');
}
});
});
</script>
@append

View File

@ -0,0 +1,416 @@
<form class="row g-0 needs-validation" method="post" action="{{ url('ftn/system/addaddress',$o->id) }}" novalidate>
<input type="hidden" id="action" name="action" value="">
@csrf
<div class="row pt-0">
<div class="col-12">
<div class="greyframe titledbox shadow0xb0">
<h2 class="cap">Assign New address</h2>
<div class="row">
<!-- Select Zone -->
<div class="col-3">
<label for="zone_id" class="form-label">Zone</label>
<div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-hash"></i></span>
<select class="form-select @error('zone_id') is-invalid @enderror" id="zone_id" name="zone_id" required>
<option></option>
@foreach(\App\Models\Zone::active()->domainZoneOrder()->with(['domain'])->get() as $zo)
<option value="{{ $zo->id }}">{{ $zo->zone_id }} <small>({{ $zo->domain->name }})</small></option>
@endforeach
</select>
<span class="invalid-feedback" role="alert">
@error('zone_id')
{{ $message }}
@else
Please select the Zone for the node's address.
@enderror
</span>
</div>
</div>
<!-- Select Region -->
<div class="col-3 d-none" id="region-select">
<label for="region_id" class="form-label">Region</label>
<div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-geo"></i></span>
<select class="form-select @error('region_id') is-invalid @enderror" id="region_id" name="region_id" required>
</select>
<span class="invalid-feedback" role="alert">
@error('region_id')
{{ $message }}
@else
Please make a choice.
@enderror
</span>
</div>
</div>
<!-- Select Host -->
<div class="col-3 d-none" id="host-select">
<label for="host_id" class="form-label">Host</label>
<div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-diagram-3-fill"></i></span>
<select class="form-select @error('host_id') is-invalid @enderror" id="host_id" name="host_id">
</select>
<span class="invalid-feedback" role="alert">
@error('host_id')
{{ $message }}
@enderror
</span>
</div>
</div>
<!-- Select Hub -->
<div class="col-3 d-none" id="hub-select">
<label for="hub_id" class="form-label">Hub</label>
<div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-diagram-2-fill"></i></span>
<select class="form-select @error('hub_id') is-invalid @enderror" id="hub_id" name="hub_id">
</select>
<span class="invalid-feedback" role="alert">
@error('hub_id')
{{ $message }}
@enderror
</span>
</div>
</div>
</div>
<div class="row">
<!-- Node/Point address -->
<div class="col-3 d-none" id="node-address">
<label for="node_id" class="form-label">Node/Point Address</label>
<div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-hash"></i></span>
<input type="text" style="width: 35%;" class="form-control @error('node_id') is-invalid @enderror" id="node_id" placeholder="Node" name="node_id" value="{{ old('node_id',$o->node_id) }}" @cannot('admin',$o)disabled @endcannot>
<span class="input-group-text ml-1 mr-1 p-0">.</span>
<input type="text" class="form-control @error('point_id') is-invalid @enderror" id="point_id" placeholder="0" name="point_id" value="{{ old('point_id',$o->point_id) ?: 0 }}" @cannot('admin',$o)disabled @endcannot style="padding-left: 0;">
<span class="invalid-feedback" role="alert">
@error('node_id')
{{ $message }}
@enderror
@error('point_id')
{{ $message }}
@enderror
</span>
</div>
</div>
<!-- Region Address -->
<div class="pl-0 col-3 d-none" id="region-address">
<label for="region_id_new" class="form-label">Region Address</label>
<div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-hash"></i></span>
<input type="text" style="width: 35%;" class="form-control @error('region_id_new') is-invalid @enderror" id="region_id_new" placeholder="Region #" name="region_id_new" value="{{ old('region_id_new') }}" @cannot('admin',$o)disabled @endcannot>
<span class="input-group-text">/0.0</span>
<span class="invalid-feedback" role="alert">
@error('region_id_new')
{{ $message }}
@else
The region number is required.
@enderror
</span>
</div>
</div>
<!-- Host Address -->
<div class="pl-0 col-3 d-none" id="host-address">
<label for="host_id_new" class="form-label">Host Address</label>
<div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-hash"></i></span>
<input type="text" class="form-control @error('host_id_new') is-invalid @enderror" id="host_id_new" placeholder="Host #" name="host_id_new" value="{{ old('host_id_new') }}" @cannot('admin',$o)disabled @endcannot>
<span class="input-group-text ml-1 mr-1 p-0">/</span>
<input type="text" class="form-control @error('node_id_new') is-invalid @enderror" id="node_id_new" placeholder="Node #" name="node_id_new" value="{{ old('node_id_new') }}" @cannot('admin',$o)disabled @endcannot>
<span class="input-group-text">.0</span>
<span class="invalid-feedback" role="alert">
@error('host_id_new')
{{ $message }}
@else
The host address is required.
@enderror
@error('node_id_new')
{{ $message }}
@else
The node address is required.
@enderror
</span>
</div>
</div>
<!-- Hub Checkbox -->
<div class="col-2 d-none" id="hub-checkbox">
<label for="hub" class="form-label">Hub</label>
<div class="input-group">
<div class="btn-group" role="group">
<input type="radio" class="btn-check" name="hub" id="hub_yes" value="1" required @cannot('admin',$o)disabled @endcannot @if(old('hub',$o->hub))checked @endif>
<label class="btn btn-outline-success" for="hub_yes">Yes</label>
<input type="radio" class="btn-check btn-danger" name="hub" id="hub_no" value="0" required @cannot('admin',$o)disabled @endcannot @if(! old('hub',$o->hub))checked @endif>
<label class="btn btn-outline-danger" for="hub_no">No</label>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-2">
<a href="{{ url('ftn/system') }}" class="btn btn-danger">Cancel</a>
</div>
<span class="col-6 mt-auto mx-auto text-center align-bottom">
@if($errors->count())
<span class="pl-5 btn btn-sm btn-danger" role="alert">
There were errors with the submission.
</span>
@endif
</span>
@can('admin',$o)
<div class="col-2">
<button type="submit" name="submit" class="btn btn-success mr-0 float-end">Add</button>
</div>
@endcan
</div>
</div>
</div>
</div>
</form>
@section('page-scripts')
<script type="text/javascript">
$(document).ready(function() {
/*
// Disable enter for form submission.
$('input').on('keydown', function(event) {
var x = event.which;
if (x === 13) {
event.preventDefault();
}
});
*/
$('#zone_id').on('change',function() {
$(this).parent().find('i').addClass('spinner-grow spinner-grow-sm');
$('#region_id').prop('disabled',true);
$('#region_id').children().remove();
if (! $('#region-address').hasClass('d-none'))
$('#region-address').addClass('d-none');
if (! $('#host-address').hasClass('d-none'))
$('#host-address').addClass('d-none');
if (! $('#host-select').hasClass('d-none'))
$('#host-select').addClass('d-none');
if (! $('#hub-select').hasClass('d-none'))
$('#hub-select').addClass('d-none')
if (! $('#hub-checkbox').hasClass('d-none'))
$('#hub-checkbox').addClass('d-none');
if (! $('#node-address').hasClass('d-none'))
$('#node-address').addClass('d-none');
$.get('{{ url('api/regions') }}'+'/'+this.value,function(data) {
$('#region_id').append('<option value=""></option>');
$('#region_id').append('<option value="0">No Region</option>');
$('#region_id').append('<option value="new">New Region</option>');
data.forEach(function(item) {
$('#region_id').append('<option value="'+item.id+'">'+item.value+'</option>');
});
$('#region_id').prop('disabled',false);
$('#region_id').show();
});
$('#region-select').removeClass('d-none');
$(this).parent().find('i').removeClass('spinner-grow spinner-grow-sm');
});
$('#region_id').on('change',function() {
switch(this.value) {
case '':
if (! $('#region-address').hasClass('d-none'))
$('#region-address').addClass('d-none');
if (! $('#host-select').hasClass('d-none'))
$('#host-select').addClass('d-none');
if (! $('#host-address').hasClass('d-none'))
$('#host-address').addClass('d-none');
if (! $('#hub-select').hasClass('d-none'))
$('#hub-select').addClass('d-none');
if (! $('#hub-checkbox').hasClass('d-none'))
$('#hub-checkbox').addClass('d-none');
if (! $('#node-address').hasClass('d-none'))
$('#node-address').addClass('d-none');
break;
case 'new':
if (! $('#host-select').hasClass('d-none'))
$('#host-select').addClass('d-none');
if (! $('#host-address').hasClass('d-none'))
$('#host-address').addClass('d-none');
if ($('#region-address').hasClass('d-none'))
$('#region-address').removeClass('d-none');
if (! $('#hub-select').hasClass('d-none'))
$('#hub-select').addClass('d-none');
if (! $('#hub-checkbox').hasClass('d-none'))
$('#hub-checkbox').addClass('d-none');
if (! $('#node-address').hasClass('d-none'))
$('#node-address').addClass('d-none');
$('#action').val('region');
break;
case '0':
default:
// Find Hosts
if ($('#host-select').hasClass('d-none'))
$('#host-select').removeClass('d-none');
if (! $('#region-address').hasClass('d-none'))
$('#region-address').addClass('d-none');
if (! $('#hub-select').hasClass('d-none'))
$('#hub-select').addClass('d-none');
if (! $('#hub-checkbox').hasClass('d-none'))
$('#hub-checkbox').addClass('d-none');
if (! $('#host-address').hasClass('d-none'))
$('#host-address').addClass('d-none');
if (! $('#node-address').hasClass('d-none'))
$('#node-address').addClass('d-none');
$(this).parent().find('i').addClass('spinner-grow spinner-grow-sm');
$('#host_id').prop('disabled',true);
$('#host_id').children().remove();
var that = this;
$.get('{{ url('api/hosts') }}'+'/'+$('#zone_id').val()+'/'+this.value,function(data) {
$('#host_id').append('<option value=""></option>');
if (that.value !== '0')
$('#host_id').append('<option value="0">No Host</option>');
$('#host_id').append('<option value="new">New Host</option>');
data.forEach(function(item) {
$('#host_id').append('<option value="'+item.id+'">'+item.value+'</option>');
});
$('#host_id').prop('disabled',false);
$('#host_id').show();
});
$('#host-select').removeClass('d-none');
$(this).parent().find('i').removeClass('spinner-grow spinner-grow-sm');
}
});
$('#host_id').on('change',function() {
switch(this.value) {
case '':
if (! $('#host-address').hasClass('d-none'))
$('#host-address').addClass('d-none');
if (! $('#hub-select').hasClass('d-none'))
$('#hub-select').addClass('d-none');
if (! $('#hub-checkbox').hasClass('d-none'))
$('#hub-checkbox').addClass('d-none');
if (! $('#node-address').hasClass('d-none'))
$('#node-address').addClass('d-none');
break;
case 'new':
if ($('#host-address').hasClass('d-none'))
$('#host-address').removeClass('d-none');
if (! $('#hub-select').hasClass('d-none'))
$('#hub-select').addClass('d-none');
if (! $('#hub-checkbox').hasClass('d-none'))
$('#hub-checkbox').addClass('d-none');
if (! $('#node-address').hasClass('d-none'))
$('#node-address').addClass('d-none');
$('#action').val('host');
break;
case '0':
default:
if (! $('#host-address').hasClass('d-none'))
$('#host-address').addClass('d-none');
if ($('#hub-select').hasClass('d-none'))
$('#hub-select').removeClass('d-none');
if ($('#hub-checkbox').hasClass('d-none'))
$('#hub-checkbox').removeClass('d-none');
if ($('#node-address').hasClass('d-none'))
$('#node-address').removeClass('d-none');
$(this).parent().find('i').addClass('spinner-grow spinner-grow-sm');
$('#hub_id').prop('disabled',true);
$('#hub_id').children().remove();
$.get('{{ url('api/hubs') }}'+'/'+$('#zone_id').val()+'/'+this.value,function(data) {
$('#hub_id').append('<option value="">No Hub</option>');
data.forEach(function(item) {
$('#hub_id').append('<option value="'+item.id+'">'+item.value+'</option>');
});
$('#hub_id').prop('disabled',false);
$('#hub_id').show();
});
$('#hub-select').removeClass('d-none');
$(this).parent().find('i').removeClass('spinner-grow spinner-grow-sm');
$('#action').val('node');
}
});
$('#hub_id').on('change',function() {
switch(this.value) {
case '':
if ($('#hub-checkbox').hasClass('d-none'))
$('#hub-checkbox').removeClass('d-none');
break;
default:
if (! $('#hub-checkbox').hasClass('d-none'))
$('#hub-checkbox').addClass('d-none');
}
});
$('#point_id').on('change',function() {
switch(this.value) {
case '0':
if ($('#hub-checkbox').hasClass('d-none'))
$('#hub-checkbox').removeClass('d-none');
break;
default:
if (! $('#hub-checkbox').hasClass('d-none'))
$('#hub-checkbox').addClass('d-none');
}
});
});
</script>
@append

View File

@ -0,0 +1,129 @@
@if(($x=\App\Models\Zone::active()
->whereIn('id',$o->zones->pluck('id'))
->whereNotIn('id',$o->sessions->pluck('id'))
->with(['domain'])
->get())->count())
<hr>
<form class="row g-0 needs-validation" method="post" action="{{ url('ftn/system/addsession',$o->id) }}" novalidate>
@csrf
<div class="row pt-0">
<div class="col-12">
<div class="greyframe titledbox shadow0xb0">
<h2 class="cap">Setup Session Details</h2>
<div class="row">
<!-- Select Zone -->
<div class="col-3">
<label for="szone_id" class="form-label">Zone</label>
<div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-hash"></i></span>
<select class="form-select @error('zone_id') is-invalid @enderror" id="szone_id" name="zone_id" required>
<option></option>
@foreach($x as $zo)
<option value="{{ $zo->id }}" @if(old('zone_id') == $zo->id)selected @endif>{{ $zo->zone_id }} <small>({{ $zo->domain->name }})</small></option>
@endforeach
</select>
<span class="invalid-feedback" role="alert">
@error('zone_id')
{{ $message }}
@else
Please select the Zone for the node's address.
@enderror
</span>
</div>
</div>
<div class="col-9">
<div class="row pt-0">
<div class="col-6">
<!-- Session -->
<label for="sespass" class="form-label">Session Password</label>
<div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-lock"></i></span>
<input type="text" style="width: 35%;" class="form-control @error('sespass') is-invalid @enderror" id="sespass" placeholder="Session" name="sespass" value="{{ old('sespass') }}" @cannot('admin',$o)disabled @endcannot required>
<span class="invalid-feedback" role="alert">
@error('sespass')
{{ $message }}
@else
Session Password required.
@enderror
</span>
</div>
</div>
<div class="col-5">
<!-- Packet -->
<label for="pktpass" class="form-label">Packet Password</label>
<div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-box"></i></span>
<input type="text" style="width: 35%;" class="form-control @error('pktpass') is-invalid @enderror" id="pktpass" placeholder="Packet" name="pktpass" value="{{ old('pktpass') }}" @cannot('admin',$o)disabled @endcannot>
<span class="invalid-feedback" role="alert">
@error('pktpass')
{{ $message }}
@enderror
</span>
</div>
</div>
</div>
<div class="row">
<div class="col-6">
<!-- Session -->
<label for="fixpass" class="form-label">Areafix Password</label>
<div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-card-text"></i></span>
<input type="text" style="width: 35%;" class="form-control @error('fixpass') is-invalid @enderror" id="fixpass" placeholder="Areafix" name="fixpass" value="{{ old('fixpass') }}" @cannot('admin',$o)disabled @endcannot required>
<span class="invalid-feedback" role="alert">
@error('fixpass')
{{ $message }}
@else
Areafix password required.
@enderror
</span>
</div>
</div>
<div class="col-5">
<!-- Packet -->
<label for="ticpass" class="form-label">TIC Password</label>
<div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-archive"></i></span>
<input type="text" style="width: 35%;" class="form-control @error('ticpass') is-invalid @enderror" id="ticpass" placeholder="TIC" name="ticpass" value="{{ old('ticpass') }}" @cannot('admin',$o)disabled @endcannot>
<span class="invalid-feedback" role="alert">
@error('ticpass')
{{ $message }}
@enderror
</span>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-2">
<a href="{{ url('ftn/system') }}" class="btn btn-danger">Cancel</a>
</div>
<span class="col-6 mt-auto mx-auto text-center align-bottom">
@if($errors->count())
<span class="pl-5 btn btn-sm btn-danger" role="alert">
There were errors with the submission.
</span>
@endif
</span>
@can('admin',$o)
<div class="col-2">
<button type="submit" name="submit" class="btn btn-success mr-0 float-end">Add</button>
</div>
@endcan
</div>
</div>
</div>
</div>
</div>
</form>
@endif

View File

@ -0,0 +1,181 @@
@php
use App\Models\Setup;
@endphp
<form class="row g-0 needs-validation" method="post" novalidate>
@csrf
<div class="row">
<div class="col-12">
<div class="greyframe titledbox shadow0xb0">
<h2 class="cap">@if($o->exists) Update @else Add @endif System</h2>
<div class="row">
<div class="col-4">
<label for="name" class="form-label">Name</label>
<div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-tag-fill"></i></span>
<input type="text" class="form-control @error('name') is-invalid @enderror" id="name" placeholder="Name" name="name" value="{{ old('name',$o->name) }}" required @cannot('admin',$o)disabled @endcannot autofocus>
<span class="invalid-feedback" role="alert">
@error('name')
{{ $message }}
@else
A name is required.
@enderror
</span>
</div>
</div>
<div class="col-2">
<label for="active" class="form-label">Active</label>
<div class="input-group">
<div class="btn-group" role="group">
<input type="radio" class="btn-check" name="active" id="active_yes" value="1" required @cannot('admin',$o)disabled @endcannot @if(old('active',$o->active))checked @endif>
<label class="btn btn-outline-success" for="active_yes">Yes</label>
<input type="radio" class="btn-check btn-danger" name="active" id="active_no" value="0" required @cannot('admin',$o)disabled @endcannot @if(! old('active',$o->active))checked @endif>
<label class="btn btn-outline-danger" for="active_no">No</label>
</div>
</div>
</div>
<div class="col-3">
<label for="zt_id" class="form-label">ZeroTier ID</label>
<div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-shield-lock-fill"></i></span>
<input type="text" class="form-control @error('zt_id') is-invalid @enderror" id="zt_id" placeholder="ZeroTier" name="zt_id" value="{{ old('zt_id',$o->zt_id) }}" @cannot('admin',$o)disabled @endcannot>
<span class="invalid-feedback" role="alert">
@error('zt_id')
{{ $message }}
@enderror
</span>
</div>
</div>
</div>
<div class="row">
<div class="col-4">
<label for="sysop" class="form-label">Sysop</label>
<div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-globe"></i></span>
<input type="text" class="form-control @error('sysop') is-invalid @enderror" id="sysop" placeholder="Sysop" name="sysop" value="{{ old('sysop',$o->sysop) }}" required @cannot('admin',$o)disabled @endcannot autocomplete="name">
<span class="invalid-feedback" role="alert">
@error('sysop')
{{ $message }}
@else
A Sysop's name is required.
@enderror
</span>
</div>
</div>
<div class="col-8">
<label for="location" class="form-label">Location</label>
<div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-globe"></i></span>
<input type="text" class="form-control @error('location') is-invalid @enderror" id="location" placeholder="Location" name="location" value="{{ old('location',$o->location) }}" required @cannot('admin',$o)disabled @endcannot>
<span class="invalid-feedback" role="alert">
@error('location')
{{ $message }}
@else
System location is required.
@enderror
</span>
</div>
</div>
</div>
<div class="row">
<div class="col-12">
<h4>Mailer Details</h4>
<div class="pt-0 row">
<div class="col-4">
<label for="method" class="form-label">Connection Method</label>
<div class="input-group">
<span class="input-group-text"><i class="bi bi-wifi"></i></span>
<select class="form-select @error('method') is-invalid @enderror" id="mailer_type" name="mailer_type" @cannot('admin',$o)disabled @endcannot>
<option></option>
<option value="{{ Setup::O_BINKP }}" @if(old('mailer_type',$o->mailer_type) == Setup::O_BINKP)selected @endif}}>BINKP</option>
<option value="{{ Setup::O_EMSI }}" @if(old('mailer_type',$o->mailer_type) == Setup::O_EMSI)selected @endif}}>EMSI</option>
</select>
</div>
</div>
<div class="col-8">
<label for="address" class="form-label">Address</label>
<div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-globe"></i></span>
<input type="text" class="w-75 form-control @error('mailer_address') is-invalid @enderror" id="mailer_address" placeholder="FQDN" name="mailer_address" value="{{ old('mailer_address',$o->mailer_address) }}" @cannot('admin',$o)disabled @endcannot>
<input type="text" class="form-control @error('mailer_port') is-invalid @enderror" id="mailer_port" placeholder="Port" name="mailer_port" value="{{ old('mailer_port',$o->mailer_port) }}" @cannot('admin',$o)disabled @endcannot>
<span class="invalid-feedback" role="alert">
@error('mailer_address')
{{ $message }}
@enderror
@error('mailer_port')
{{ $message }}
@enderror
</span>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-12">
<h4>BBS Details</h4>
<div class="pt-0 row">
<div class="col-4">
<label for="method" class="form-label">Connection Method</label>
<div class="input-group">
<span class="input-group-text"><i class="bi bi-wifi"></i></span>
<select class="form-select @error('method') is-invalid @enderror" id="method" name="method" @cannot('admin',$o)disabled @endcannot>
<option></option>
<option value="23" @if(old('method',$o->method) == 23)selected @endif}}>Telnet</option>
<option value="22" @if(old('method',$o->method) == 22)selected @endif}}>SSH</option>
<option value="519" @if(old('method',$o->method) == 519)selected @endif}}>Rlogin</option>
</select>
</div>
</div>
<div class="col-8">
<label for="address" class="form-label">Address</label>
<div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-globe"></i></span>
<input type="text" class="w-75 form-control @error('address') is-invalid @enderror" id="address" placeholder="FQDN" name="address" value="{{ old('address',$o->address) }}" @cannot('admin',$o)disabled @endcannot>
<input type="text" class="form-control @error('port') is-invalid @enderror" id="port" placeholder="Port" name="port" value="{{ old('port',$o->port) }}" @cannot('admin',$o)disabled @endcannot>
<span class="invalid-feedback" role="alert">
@error('address')
{{ $message }}
@enderror
@error('port')
{{ $message }}
@enderror
</span>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-12">
<label for="notes" class="form-label">Notes</label>
<textarea class="form-control" rows=3 name="notes" placeholder="Notes..." @cannot('admin',$o)disabled @endcannot>{{ old('notes',$o->notes) }}</textarea>
</div>
</div>
<div class="row">
<div class="col-12">
<a href="{{ url('ftn/system') }}" class="btn btn-danger">Cancel</a>
@can('admin',$o)
<button type="submit" name="submit" class="btn btn-success mr-0 float-end">@if ($o->exists)Save @else Add @endif</button>
@endcan
</div>
</div>
</div>
</div>
</div>
</form>

View File

@ -0,0 +1,93 @@
@extends('layouts.app')
@section('htmlheader_title')
Systems
@endsection
@section('content')
<div class="row">
<div class="col-12">
<h2>Our Systems</h2>
@if (\App\Models\System::count() == 0)
<p class="pad">There are no systems configured here.</p>
@else
<p>These BBS systems are configured here.</p>
<table class="table monotable" id="systems">
<thead>
<tr>
<th>Domain</th>
<th>ID</th>
<th>System</th>
<th>Sysop</th>
<th>Location</th>
<th>Connect</th>
<th>Address</th>
<th>ZeroTier ID</th>
</tr>
</thead>
<tbody>
@foreach (\App\Models\SystemZone::select('*')->with(['system','zone.domain'])->get() as $oo)
<tr>
<td>{{ $oo->zone->domain->name }}</td>
<td><a href="{{ url('ftn/system/addedit',[$oo->system_id]) }}">{{ $oo->system_id }}</a></td>
<td>{{ $oo->system->name }}</td>
<td>{{ $oo->system->sysop }}</td>
<td>{{ $oo->system->location }}</td>
<td>
@switch($oo->system->method)
@case(23)<a href="telnet://{{ $oo->system->address }}:{{ $oo->system->port }}">Telnet</a>@break
@case(22)<a href="ssh://{{ $oo->system->address }}:{{ $oo->system->port }}">SSH</a>@break
@case(519)<a href="rlogin://{{ $oo->system->address }}:{{ $oo->system->port }}">SSH</a>@break
@default No details
@endswitch
</td>
<td>{{ join(',',$oo->system->addresses->where('zone_id',$oo->zone_id)->pluck('ftn')->toArray()) }}</td>
<td>{{ $oo->system->zt_id }}</td>
</tr>
@endforeach
</tbody>
</table>
@endif
</div>
</div>
@endsection
@section('page-scripts')
<link type="text/css" rel="stylesheet" href="https://cdn.datatables.net/1.10.25/css/dataTables.bootstrap5.min.css" media="screen" >
<link type="text/css" rel="stylesheet" href="{{ asset('plugin/dataTables/dataTables.bootstrap5.css') }}" media="screen">
<script type="text/javascript" src="https://cdn.datatables.net/1.10.25/js/jquery.dataTables.min.js"></script>
<script type="text/javascript" src="https://cdn.datatables.net/rowgroup/1.1.2/js/dataTables.rowGroup.min.js"></script>
<script type="text/javascript" src="https://cdn.datatables.net/1.10.25/js/dataTables.bootstrap5.min.js"></script>
<script type="text/javascript">
$('table tr').click(function() {
var href = $(this).find('a').attr('href');
if (href)
window.location = href;
});
$('#systems').DataTable({
paging: true,
pageLength: 25,
searching: true,
autoWidth: false,
order: [
[0,'asc'],
[2,'asc']
],
rowGroup: {
dataSrc: [0],
},
columnDefs: [
{
targets: [0],
visible: false,
},
],
});
</script>
@append

View File

@ -42,11 +42,19 @@ Route::middleware(['verified','activeuser'])->group(function () {
Route::get('ftn/system',[SystemController::class,'home']); Route::get('ftn/system',[SystemController::class,'home']);
Route::match(['get','post'],'ftn/system/addedit/{o?}',[SystemController::class,'add_edit']) Route::match(['get','post'],'ftn/system/addedit/{o?}',[SystemController::class,'add_edit'])
->where('o','[0-9]+'); ->where('o','[0-9]+');
Route::post('ftn/system/addaddress/{o?}',[SystemController::class,'add_address'])
Route::get('ftn/our_systems',[SystemController::class,'ours']);
Route::post('ftn/system/addaddress/{o}',[SystemController::class,'add_address'])
->where('o','[0-9]+'); ->where('o','[0-9]+');
Route::get('ftn/system/deladdress/{o?}',[SystemController::class,'del_address']) Route::post('ftn/system/addsession/{o}',[SystemController::class,'add_session'])
->where('o','[0-9]+'); ->where('o','[0-9]+');
Route::get('ftn/system/susaddress/{o?}',[SystemController::class,'sus_address']) Route::get('ftn/system/deladdress/{o}',[SystemController::class,'del_address'])
->where('o','[0-9]+');
Route::get('ftn/system/delsession/{o}/{zo}',[SystemController::class,'del_session'])
->where('o','[0-9]+')
->where('zo','[0-9]+');
Route::get('ftn/system/susaddress/{o}',[SystemController::class,'sus_address'])
->where('o','[0-9]+'); ->where('o','[0-9]+');
Route::get('ftn/zone',[ZoneController::class,'home']); Route::get('ftn/zone',[ZoneController::class,'home']);