diff --git a/app/Http/Controllers/DomainController.php b/app/Http/Controllers/DomainController.php index 3118b15..20378ab 100644 --- a/app/Http/Controllers/DomainController.php +++ b/app/Http/Controllers/DomainController.php @@ -19,11 +19,13 @@ class DomainController extends Controller public function add_edit(Request $request,Domain $o) { if ($request->post()) { + $this->authorize('admin',$o); + $request->validate([ 'name' => 'required|max:8|unique:domains,name,'.($o->exists ? $o->id : 0), 'dnsdomain' => 'nullable|regex:/^(?!:\/\/)(?=.{1,255}$)((.{1,63}\.){1,127}(?![0-9]*$)[a-z0-9-]+\.?)$/i|unique:domains,dnsdomain,'.($o->exists ? $o->id : NULL), - 'active' => 'required', - 'public' => 'required', + 'active' => 'required|boolean', + 'public' => 'required|boolean', ]); foreach (['name','dnsdomain','active','public','homepage','notes'] as $key) diff --git a/app/Http/Controllers/SystemController.php b/app/Http/Controllers/SystemController.php index 483411c..0c5cbbd 100644 --- a/app/Http/Controllers/SystemController.php +++ b/app/Http/Controllers/SystemController.php @@ -19,12 +19,15 @@ class SystemController extends Controller public function add_edit(Request $request,System $o) { if ($request->post()) { + $this->authorize('admin',$o); + $request->validate([ 'name' => 'required|min:3|unique:systems,name,'.($o->exists ? $o->id : 0), 'location' => 'required|min:3', 'sysop' => 'required|min:3', 'address' => 'nullable|regex:/^(?!:\/\/)(?=.{1,255}$)((.{1,63}\.){1,127}(?![0-9]*$)[a-z0-9-]+\.?)$/i', 'port' => 'nullable|digits_between:2,5', + 'active' => 'required|boolean', ]); foreach (['name','location','sysop','address','port','active','method','notes'] as $key) diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php index 7aba135..d306dec 100644 --- a/app/Http/Controllers/UserController.php +++ b/app/Http/Controllers/UserController.php @@ -19,6 +19,8 @@ class UserController extends Controller public function add_edit(Request $request,User $o) { if ($request->post()) { + $this->authorize('admin',$o); + $request->validate([ 'email' => 'required|email|unique:users,email,'.($o ? $o->id : NULL), ]); diff --git a/app/Http/Controllers/ZoneController.php b/app/Http/Controllers/ZoneController.php index 617fe50..c6a5636 100644 --- a/app/Http/Controllers/ZoneController.php +++ b/app/Http/Controllers/ZoneController.php @@ -3,6 +3,7 @@ namespace App\Http\Controllers; use Illuminate\Http\Request; +use Illuminate\Validation\Rule; use App\Models\Zone; @@ -19,10 +20,28 @@ class ZoneController extends Controller public function add_edit(Request $request,Zone $o) { if ($request->post()) { - foreach (['zone_id','name','active','description','notes','domain_id'] as $key) + $this->authorize('admin',$o); + + $request->validate([ + 'domain_id' => 'required|exists:domains,id', + 'zone_id' => [ + 'required', + 'digits_between:1,5', + Rule::unique('zones')->where(function ($query) use ($request,$o) { + return $query->where('domain_id',$request->post('domain_id')) + ->when($o->exists,function($query) use ($o) { + return $query->where('id','<>',$o->id); + }); + }) + ], + 'system_id' => 'required|exists:systems,id', + 'ztid' => 'nullable|size:10|regex:/^([A-Fa-f0-9]){10}$/', + 'active' => 'required|boolean', + ]); + + foreach (['zone_id','domain_id','system_id','active','notes','ztid'] as $key) $o->{$key} = $request->post($key); - $o->active = TRUE; $o->save(); return redirect()->action([self::class,'home']); diff --git a/database/migrations/2021_06_18_112022_update_zones.php b/database/migrations/2021_06_18_112022_update_zones.php new file mode 100644 index 0000000..1aaf759 --- /dev/null +++ b/database/migrations/2021_06_18_112022_update_zones.php @@ -0,0 +1,51 @@ +dropColumn(['name','description','ipv4','ipv4_mask','ipv6','ipv6_mask','zt_id']); + $table->string('ztid')->nullable(); + $table->dropUnique(['domain_id']); + + $table->integer('system_id'); + $table->foreign('system_id')->references('id')->on('systems'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + DB::statement('ALTER TABLE zones ALTER COLUMN domain_id DROP NOT NULL'); + + Schema::table('zones', function (Blueprint $table) { + $table->dropForeign(['system_id']); + $table->dropColumn(['system_id','ztid']); + $table->unique('domain_id'); + + $table->string('name'); + $table->string('description'); + $table->ipAddress('ipv4')->nullable(); + $table->integer('ipv4_mask')->nullable(); + $table->ipAddress('ipv6')->nullable(); + $table->integer('ipv6_mask')->nullable(); + $table->binary('zt_id')->nullable()->unique(); + }); + } +} diff --git a/public/oldschool/css/main.css b/public/oldschool/css/main.css index 32236d6..daf8da7 100644 --- a/public/oldschool/css/main.css +++ b/public/oldschool/css/main.css @@ -49,6 +49,13 @@ a.disabled { text-transform:uppercase } +.input-helper { + display: block; + margin-top: .25rem; + font-size: .875em; + width: 100%; +} + strong.highlight { color: #eee; } @@ -234,9 +241,6 @@ ul#navlist-desktop { box-sizing:border-box; overflow:hidden } -#content * { - vertical-align:top -} #content a.anchor { display:block; position:relative; diff --git a/public/plugin/dataTables/dataTables.bootstrap5.css b/public/plugin/dataTables/dataTables.bootstrap5.css new file mode 100644 index 0000000..bb946cf --- /dev/null +++ b/public/plugin/dataTables/dataTables.bootstrap5.css @@ -0,0 +1,35 @@ +table.dataTable { + border-collapse: collapse !important; +} + +div.dataTables_wrapper div.dataTables_filter { + text-align: right; + color: #eeeeee; + padding-bottom: 20px; +} +div.dataTables_wrapper div.dataTables_filter input { + margin-left: 0.5em; + display: inline; + background-color: #000; + color: #eeeeee; +} + +div.dataTables_wrapper div.dataTables_info { + padding-top: 0.85em; + white-space: nowrap; + font-size: 75%; + color: #eeeeee; +} + +table.dataTable thead .sorting:before, +table.dataTable thead .sorting_asc:before, +table.dataTable thead .sorting_desc:before, +table.dataTable thead .sorting_asc_disabled:before, +table.dataTable thead .sorting_desc_disabled:before, +table.dataTable thead .sorting:after, +table.dataTable thead .sorting_asc:after, +table.dataTable thead .sorting_desc:after, +table.dataTable thead .sorting_asc_disabled:after, +table.dataTable thead .sorting_desc_disabled:after { + color: #eeeeee; +} \ No newline at end of file diff --git a/resources/views/auth/permissions.blade.php b/resources/views/auth/permissions.blade.php index 237636b..bb4b694 100644 --- a/resources/views/auth/permissions.blade.php +++ b/resources/views/auth/permissions.blade.php @@ -25,7 +25,7 @@ - + @@ -41,6 +41,52 @@
DomainDomain Result
+ + + System + + + + + + + + + + + @foreach (\App\Models\System::orderBy('name')->get() as $o) + + + + + @endforeach + +
SystemResult
{{ $o->name }}@can('admin',$o)YES @else NO @endcan
+ + + + + Zone + + + + + + + + + + + @foreach (\App\Models\Zone::orderBy('zone_id')->get() as $o) + + + + + @endforeach + +
ZoneResult
{{ $o->zone_id }}@can('admin',$o)YES @else NO @endcan
+ + @endsection diff --git a/resources/views/domain/addedit.blade.php b/resources/views/domain/addedit.blade.php index a572d6a..25f793f 100644 --- a/resources/views/domain/addedit.blade.php +++ b/resources/views/domain/addedit.blade.php @@ -18,7 +18,7 @@
- + @error('name') {{ $message }} @@ -33,12 +33,12 @@
-
+
- active))checked @endif> + active))checked @endif> - active))checked @endif> + active))checked @endif>
@@ -50,23 +50,23 @@
- - @error('dnsdomain') - + + + @error('dnsdomain') {{ $message }} - - @enderror + @enderror +
-
+
- public))checked @endif> + public))checked @endif> - public))checked @endif> + public))checked @endif>
@@ -76,7 +76,7 @@
- +
@@ -92,7 +92,7 @@
- +
@@ -101,7 +101,9 @@
Cancel - + @can('admin',$o) + + @endcan
@@ -110,10 +112,12 @@ @endsection @section('page-scripts') - - + @can('admin',$o) + + - + + @endcan @append \ No newline at end of file diff --git a/resources/views/domain/home.blade.php b/resources/views/domain/home.blade.php index fc4da50..bbb0062 100644 --- a/resources/views/domain/home.blade.php +++ b/resources/views/domain/home.blade.php @@ -7,7 +7,7 @@

About FTN Domains

-

In FTN network addresses, a domain is the 5th dimension and used when a system supports 5D addressing, ie: zone:hub/host@domain.

+

In FTN network addresses, a domain is the 5th dimension and used when a system supports 5D addressing, ie: zone:hub/host.point@domain.

Domains are used with zones to uniquely identify a FTN network.

Some legacy Fidonet software is not 5D aware and may behave unexpectedly when a domain is used

@@ -36,7 +36,7 @@ - @can('admin',(new \App\Models\Domain())) + @can('admin',(new \App\Models\Domain)) Add New Domain diff --git a/resources/views/system/addedit.blade.php b/resources/views/system/addedit.blade.php new file mode 100644 index 0000000..6ad3ad6 --- /dev/null +++ b/resources/views/system/addedit.blade.php @@ -0,0 +1,139 @@ +@extends('layouts.app') + +@section('htmlheader_title') + @if($o->exists) Update @else Add @endif System +@endsection + +@section('content') +
+ @csrf + +
+
+
+

@if($o->exists) Update @else Add @endif System

+ +
+
+ +
+ + + @error('name') + + {{ $message }} + + @else + + A name is required. + + @enderror +
+
+ +
+ +
+
+ active))checked @endif> + + + active))checked @endif> + +
+
+
+
+ +
+
+ +
+ + + @error('sysop') + + {{ $message }} + + @else + + A Sysop's name is required. + + @enderror +
+
+ +
+ +
+ + + @error('location') + + {{ $message }} + + @else + + System location is required. + + @enderror +
+
+
+ +
+
+ +
+ + +
+
+ +
+ +
+ + + + + + @error('address') + + {{ $message }} + + @enderror + @error('port') + + {{ $message }} + + @enderror +
+
+
+ +
+
+ + +
+
+ +
+
+ Cancel + @can('admin',$o) + + @endcan +
+
+
+
+
+
+@endsection diff --git a/resources/views/user/home.blade.php b/resources/views/user/home.blade.php index 5153bef..fd9f260 100644 --- a/resources/views/user/home.blade.php +++ b/resources/views/user/home.blade.php @@ -19,7 +19,7 @@ - @can('admin',(new \App\Models\Domain())) + @can('admin',(new \App\Models\User)) Add New User diff --git a/resources/views/zone/addedit.blade.php b/resources/views/zone/addedit.blade.php index edd742a..eab7f80 100644 --- a/resources/views/zone/addedit.blade.php +++ b/resources/views/zone/addedit.blade.php @@ -4,70 +4,125 @@ @if($o->exists) Update @else Add @endif Zone @endsection -@section('main-content') -
-

@if($o->exists) Update @else Add @endif Zone

+@section('content') +
+ @csrf - - {{ csrf_field() }} +
+
+
+

@if($o->exists) Update @else Add @endif Zone

-
-
-
-
- - -
- -
- - -
- -
- - -
- -
- - -
- -
- -
-
- active)checked @endif> - -
- -
- active)checked @endif> - -
+
+
+ +
+ + + @error('zone_id') + + {{ $message }} + + @else + + A zone number is required. + + @enderror
-
- - +
+ +
+ + + @error('domain_id') + + {{ $message }} + + @else + + A domain is required. + + @enderror + Add a NEW Domain +
-
-
- - Cancel +
+ +
+ + + @error('system_id') + + {{ $message }} + + @else + + A system is required. + + @enderror + Add a NEW System. This system is the primary mailer/tosser responsible for managing the zone.
+ +
+ +
+
+ active))checked @endif> + + + active))checked @endif> + +
+
+
+
+ +
+
+ +
+ + + + @error('ztid') + {{ $message }} + @enderror + +
+
+
+ +
+
+ + +
+
+ +
+
+ Cancel + @can('admin',$o) + + @endcan +
- -
+
+ @endsection diff --git a/resources/views/zone/home.blade.php b/resources/views/zone/home.blade.php index 0769dab..89f8731 100644 --- a/resources/views/zone/home.blade.php +++ b/resources/views/zone/home.blade.php @@ -3,38 +3,68 @@ FTN Zones @endsection -@section('main-content') +@section('content') +
+
+

About FTN Zones

+

In FTN network addresses, a zone is the 3rd dimension and used when a system supports 3D (or better) addressing, ie: zone:hub/host.point@domain.

+

Zones are used with domains to uniquely identify a FTN network. Within an FTN network there can be multiple zones with the same domain.

+

It is rare that a domain has multiple zones - unless it grows quite large. Zones can also be used to group systems into a common boundary.

+
+
+
- - - - - - - - - +

This system is aware of the following zones in each domain:

- - - - - @foreach (\App\Models\Zone::cursor() as $oo) + @if (\App\Models\Zone::count() == 0) + @can('admin',(new \App\Models\Zone)) +

There are no zones setup, to set up your first.

+ @else +

There are no zones - you need to ask an admin to create one for you.

+ @endcan + @else + @can('admin',(new \App\Models\Domain)) +

You can Add New Zone.

+ @endcan +
IDActiveZoneDomain
Add New Zone
+ - - - - + + + + - @endforeach - -
{{ $oo->zone_id }}{{ $oo->active ? 'YES' : 'NO' }}{{ $oo->name }}{{ $oo->domain->name }}DomainZoneActiveSystems
+ + + + @foreach (\App\Models\Zone::with(['domain'])->cursor() as $oo) + + {{ $oo->domain->name }} + {{ $oo->zone_id }} + {{ $oo->active ? 'YES' : 'NO' }} + - + + @endforeach + + + @endif
@endsection @section('page-scripts') +{{-- + + +--}} + + + + + + + @append