More changes to use form.select component. Re-engineered user BBS registration

This commit is contained in:
Deon George 2024-12-06 08:33:24 +11:00
parent fd780d1756
commit e7336a942b
13 changed files with 253 additions and 422 deletions

View File

@ -49,6 +49,9 @@ class SystemController extends Controller
$o->autohold = FALSE; $o->autohold = FALSE;
$o->save(); $o->save();
if ($o->wasRecentlyCreated)
$o->users()->attach(Auth::id());
$mailers = collect($request->post('mailer_details')) $mailers = collect($request->post('mailer_details'))
->filter(function($item) { return $item['port']; }) ->filter(function($item) { return $item['port']; })
->transform(function($item) { $item['active'] = Arr::get($item,'active',FALSE); return $item; }); ->transform(function($item) { $item['active'] = Arr::get($item,'active',FALSE); return $item; });
@ -621,39 +624,19 @@ class SystemController extends Controller
*/ */
public function register(SystemRegisterRequest $request) public function register(SystemRegisterRequest $request)
{ {
if ($request->action === 'register' && $request->name && is_numeric($request->name)) // During the BBS linking process, if the user selected a system will link to confirm it
return view('user.system.widget.register_confirm') if ($request->action === 'register' && $request->system_id && is_numeric($request->system_id))
->with('o',System::findOrFail($request->name)); return redirect()
->to(sprintf('user/system/register_confirm/%d',$request->system_id));
$o = System::findOrNew(is_numeric($request->system_id) ? $request->system_id : NULL); // Re-flash our previously input data, we must be creating a new system
session()->flashInput([
'name'=>$request->system_id,
'sysop'=>Auth::user()->name,
]);
// If the system doesnt exist, we'll create it return redirect()
if (! $o->exist) { ->to('system/addedit');
$o->sysop = Auth::user()->name;
foreach (['name','zt_id','location','phone','method','address','port'] as $item)
if ($request->{$item})
$o->{$item} = $request->{$item};
$o->active = TRUE;
}
if ($request->post('submit')) {
Auth::user()->systems()->save($o);
// @todo if the system already exists and part of one of our networks, we'll need to send the registration email to confirm the address.
// @todo mark the system (or addresses) as "pending" at this stage until it is confirmed
return redirect()->to(url('system/addedit',$o->id));
}
// Re-flash our previously input data
if ($request->old)
session()->flashInput($request->old);
return view('system.widget.system')
->with('action',$request->action)
->with('o',$o)
->with('errors',new ViewErrorBag);
} }
/** /**

View File

@ -56,8 +56,11 @@ class SystemRegisterRequest extends FormRequest
return []; return [];
$so = $this->route('o'); $so = $this->route('o');
// When we have selected a system during the register/linking process
if ((! $so) && ($request->action === 'register')) if ((! $so) && ($request->action === 'register'))
return []; // If system ID is not numeric, then its a new system
return is_numeric($request->system_id) ? ['system_id'=>'required|exists:systems,id'] : [];
return array_filter(array_merge([ return array_filter(array_merge([
'name' => 'required|min:3', 'name' => 'required|min:3',
@ -68,14 +71,16 @@ class SystemRegisterRequest extends FormRequest
'port' => 'nullable|digits_between:2,5', 'port' => 'nullable|digits_between:2,5',
'method' => 'nullable|numeric', 'method' => 'nullable|numeric',
'mailer_details.*' => 'nullable|array', 'mailer_details.*' => 'nullable|array',
// @todo Port should be present if active is true
'mailer_details.*.port' => 'nullable|digits_between:2,5', 'mailer_details.*.port' => 'nullable|digits_between:2,5',
'mailer_details.*.active' => 'sometimes|boolean',
'zt_id' => 'nullable|size:10|regex:/^([A-Fa-f0-9]){10}$/|unique:systems,zt_id,'.($so ? $so->id : 0), 'zt_id' => 'nullable|size:10|regex:/^([A-Fa-f0-9]){10}$/|unique:systems,zt_id,'.($so ? $so->id : 0),
'pkt_type' => ['required',Rule::in(array_keys(Packet::PACKET_TYPES))], 'pkt_type' => ['required',Rule::in(array_keys(Packet::PACKET_TYPES))],
],($so && $so->exists) ? [
'users' => 'nullable|array|min:1|max:2',
'active' => 'required|boolean', 'active' => 'required|boolean',
'hold' => 'sometimes|boolean', 'hold' => 'sometimes|boolean',
'pollmode' => 'required|integer|min:0|max:2', 'pollmode' => 'required|integer|min:0|max:2',
],($so && $so->exists) ? [
'users' => 'nullable|array|min:1|max:2',
'heartbeat' => [ 'heartbeat' => [
'nullable', 'nullable',
'integer', 'integer',

View File

@ -25,6 +25,13 @@ class SystemPolicy
{ {
use HandlesAuthorization; use HandlesAuthorization;
public function admin(User $user, System $system): bool
{
// Site Admins can always create
// If it doesnt exist, then a user can create it.
return ($user->isAdmin() || (! $system->exists));
}
/** /**
* Determine whether the user can create the model. * Determine whether the user can create the model.
* *
@ -70,9 +77,9 @@ class SystemPolicy
if ($user->isAdmin()) if ($user->isAdmin())
return TRUE; return TRUE;
// If it doesnt exist, then its a false. // If it doesnt exist, then its a true (they are creating it).
if (! $system->exists) if (! $system->exists)
return FALSE; return TRUE;
// @todo Permit ZC, RC, NC, HUB user // @todo Permit ZC, RC, NC, HUB user

View File

@ -10,6 +10,7 @@ use Illuminate\Support\Facades\Blade;
use Illuminate\Support\Facades\Event; use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\Gate; use Illuminate\Support\Facades\Gate;
use Illuminate\Support\Facades\Notification; use Illuminate\Support\Facades\Notification;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\ServiceProvider; use Illuminate\Support\ServiceProvider;
use App\Events\Echomail as EchomailEvent; use App\Events\Echomail as EchomailEvent;
@ -18,7 +19,7 @@ use App\Helpers\PageAssets;
use App\Listeners\EchomailListener; use App\Listeners\EchomailListener;
use App\Listeners\Matrix\MessageListener; use App\Listeners\Matrix\MessageListener;
use App\Notifications\Channels\{EchomailChannel,MatrixChannel,NetmailChannel}; use App\Notifications\Channels\{EchomailChannel,MatrixChannel,NetmailChannel};
use App\Models\{Echomail,Netmail,User}; use App\Models\{Echomail,Netmail,System,User};
use App\Traits\Single; use App\Traits\Single;
class AppServiceProvider extends ServiceProvider class AppServiceProvider extends ServiceProvider
@ -85,5 +86,7 @@ class AppServiceProvider extends ServiceProvider
// Custom Aliases // Custom Aliases
$loader = AliasLoader::getInstance(); $loader = AliasLoader::getInstance();
$loader->alias('PageAssets',PageAssets::class); $loader->alias('PageAssets',PageAssets::class);
Route::model('so',System::class);
} }
} }

View File

@ -1,6 +1,6 @@
<x-form.base {{ $attributes }}> <x-form.base {{ $attributes }}>
<input type="hidden" id="{{ $name }}_disabled" name="{{ $name }}" value="" disabled> <input type="hidden" id="{{ $name }}_disabled" name="{{ $name }}" value="" disabled>
<select style="width: 80%" class="form-select @error((! empty($old)) ? $old : $name) is-invalid @enderror" id="{{ $id ?? $name }}" name="{{ $name }}" @required(isset($required)) @disabled(isset($disabled))> <select style="width: 80%" class="form-select @error((! empty($old)) ? $old : $name) is-invalid @enderror" id="{{ $id ?? $name }}" name="{{ $name }}" @required(isset($required)) @disabled(isset($disabled) && $disabled)>
@if(empty($value) || isset($addnew) || isset($choose)) @if(empty($value) || isset($addnew) || isset($choose))
<option value=""></option> <option value=""></option>
@isset($addnew) @isset($addnew)

View File

@ -1,8 +1,8 @@
<!-- $o = Setup::class --> <!-- $o = Setup::class -->
@php @use(App\Classes\Protocol\Binkp)
use App\Models\Setup; @use(App\Classes\Protocol\EMSI)
use App\Classes\Protocol\{Binkp,EMSI,DNS}; @use(App\Models\Setup)
@endphp @use(App\Models\System)
@extends('layouts.app') @extends('layouts.app')
@section('htmlheader_title') @section('htmlheader_title')
@ -23,30 +23,12 @@ use App\Classes\Protocol\{Binkp,EMSI,DNS};
<div class="row"> <div class="row">
<!-- System --> <!-- System -->
<div class="col-4"> <div class="col-4">
<label for="system_id" class="form-label">System</label> @php
<div class="input-group has-validation"> $helper = (! $o->system_id)
<span class="input-group-text"><i class="bi bi-tag-fill"></i></span> ? sprintf('Add a <a href="%s">NEW System"</a>',url('system/addedit'))
<select style="width: 80%;" class="form-select @error('system_id') is-invalid @enderror" id="system_id" name="system_id" required @cannot('admin',$o)disabled @endcannot> : sprintf('<a href="%s">Edit</a> System',url('system/addedit',[$o->system_id]));
<option value="">&nbsp;</option> @endphp
@foreach (\App\Models\System::active()->cursor() as $oo) <x-form.select name="system_id" icon="bi-tag-fill" label="System" feedback="A system is required" placeholder="Select System" :helper="$helper" :required="true" :value="$o->system_id" :options="System::select(['id','name'])->active()->cursor()->map(fn($item,$key)=>['id'=>$item->id,'value'=>$item->name])" />
<option value="{{ $oo->id }}" @if(old('system_id',$o->system_id)==$oo->id)selected @endif>{{ $oo->name }}</option>
@endforeach
</select>
<span class="invalid-feedback" role="alert">
@error('system_id')
{{ $message }}
@else
A system is required.
@enderror
</span>
<span class="input-helper">
@if(! $o->system_id)
Add a <a href="{{ url('system/addedit') }}">NEW System</a>
@else
<a href="{{ url('system/addedit',[$o->system_id]) }}">Edit</a> System
@endif
</span>
</div>
</div> </div>
<!-- System Addresses --> <!-- System Addresses -->
@ -301,23 +283,9 @@ use App\Classes\Protocol\{Binkp,EMSI,DNS};
@endsection @endsection
@section('page-css') @section('page-css')
@css('select2')
<style> <style>
#content h3 { #content h3 {
margin-bottom: 5px; margin-bottom: 5px;
} }
#content ul li:last-child {
margin-bottom: inherit;
}
</style> </style>
@append
@section('page-scripts')
@js('select2')
<script type="text/javascript">
$(document).ready(function() {
$('#system_id').select2();
});
</script>
@append @append

View File

@ -617,39 +617,47 @@
@section('page-scripts') @section('page-scripts')
<script type="text/javascript"> <script type="text/javascript">
$(document).ready(function () { $(document).ready(function () {
@can('admin') if (window.location.hash) {
$('.default').click(function () { $('#collapse_'+window.location.hash.substring(1)).show();
var item = this; $('#collapse_system').collapse()
icon = $(item).find('i'); }
$.ajax({ @if($o->exists)
type: 'POST', @can('admin')
data: {sid: {{$o->id}}, _token: '{{csrf_token()}}', set: (icon.hasClass('bi-square') ? 1 : 0)}, $('.default').click(function () {
beforeSend: function () { var item = this;
$(item).find('i').addClass('spinner-grow spinner-grow-sm'); icon = $(item).find('i');
},
success: function () {
if (icon.hasClass('bi-square')) {
icon.removeClass('bi-square');
icon.addClass('bi-check-square');
} else {
icon.removeClass('bi-check-square');
icon.addClass('bi-square');
}
$(item).find('i').removeClass('spinner-grow spinner-grow-sm'); $.ajax({
}, type: 'POST',
error: function (e) { data: {sid: {{$o->id}}, _token: '{{csrf_token()}}', set: (icon.hasClass('bi-square') ? 1 : 0)},
$(item).find('i').removeClass('spinner-grow spinner-grow-sm'); beforeSend: function () {
$(item).find('i').addClass('spinner-grow spinner-grow-sm');
},
success: function () {
if (icon.hasClass('bi-square')) {
icon.removeClass('bi-square');
icon.addClass('bi-check-square');
} else {
icon.removeClass('bi-check-square');
icon.addClass('bi-square');
}
$(item).find('i').removeClass('spinner-grow spinner-grow-sm');
},
error: function (e) {
$(item).find('i').removeClass('spinner-grow spinner-grow-sm');
if (e.status != 412)
alert('That didnt work? Please try again....');
},
url: '{{ url('zone/api/default') }}/' + item.attributes.itemid.nodeValue,
cache: false
})
});
@endcan
@endif
if (e.status != 412)
alert('That didnt work? Please try again....');
},
url: '{{ url('zone/api/default') }}/' + item.attributes.itemid.nodeValue,
cache: false
})
});
@endcan
$('data.validated').on('click',function(item) { $('data.validated').on('click',function(item) {
that = $(this); that = $(this);
var values = item.delegateTarget.value.split(':'); var values = item.delegateTarget.value.split(':');

View File

@ -1,3 +1,5 @@
@use(App\Models\Zone)
<form class="needs-validation" method="post" action="{{ url('system/address/add',$o->id) }}" novalidate> <form class="needs-validation" method="post" action="{{ url('system/address/add',$o->id) }}" novalidate>
@csrf @csrf
<input type="hidden" id="action" name="action" value=""> <input type="hidden" id="action" name="action" value="">
@ -8,70 +10,22 @@
<div class="row"> <div class="row">
<!-- Select Zone --> <!-- Select Zone -->
<div class="col-3"> <div class="col-3">
<label for="zone_id" class="form-label">Zone</label> <x-form.select name="zone_id" icon="bi-hash" label="Zone" :options="Zone::select(['id','zone_id','domain_id'])->active()->domainZoneOrder()->with(['domain'])->get()->map(fn($item,$key)=>['id'=>$item->id,'value'=>sprintf('%d [%s]',$item->zone_id,$item->domain->name)])" required="true" />
<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> </div>
<!-- Select Region --> <!-- Select Region -->
<div class="col-3 d-none" id="region-select"> <div class="col-3 d-none" id="region-select">
<label for="region_id" class="form-label">Region</label> <x-form.select name="region_id" icon="bi-geo" label="Region" :required="true" />
<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> </div>
<!-- Select Host --> <!-- Select Host -->
<div class="col-3 d-none" id="host-select"> <div class="col-3 d-none" id="host-select">
<label for="host_id" class="form-label">Host</label> <x-form.select name="host_id" icon="bi-diagram-3-fill" label="Host" />
<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> </div>
<!-- Select Hub --> <!-- Select Hub -->
<div class="col-3 d-none" id="hub-select"> <div class="col-3 d-none" id="hub-select">
<label for="hub_id" class="form-label">Hub</label> <x-form.select name="hub_id" icon="bi-diagram-2-fill" label="Hub" />
<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> </div>
@ -81,9 +35,9 @@
<label for="node_id" class="form-label">Node/Point Address</label> <label for="node_id" class="form-label">Node/Point Address</label>
<div class="input-group has-validation"> <div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-hash"></i></span> <span class="input-group-text"><i class="bi bi-hash"></i></span>
<input type="text" style="width: 35%;" class="form-control text-end @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> <input type="text" style="width: 35%;" class="form-control text-end @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 data-1p-ignore>
<span class="input-group-text p-0">.</span> <span class="input-group-text 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;"> <input type="text" class="form-control pl-0 @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>
<span class="invalid-feedback" role="alert"> <span class="invalid-feedback" role="alert">
@error('node_id') @error('node_id')
{{ $message }} {{ $message }}
@ -100,7 +54,7 @@
<label for="region_id_new" class="form-label">Region Address</label> <label for="region_id_new" class="form-label">Region Address</label>
<div class="input-group has-validation"> <div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-hash"></i></span> <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> <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 data-1p-ignore>
<span class="input-group-text">/0.0</span> <span class="input-group-text">/0.0</span>
<span class="invalid-feedback" role="alert"> <span class="invalid-feedback" role="alert">
@error('region_id_new') @error('region_id_new')
@ -117,7 +71,7 @@
<label for="host_id_new" class="form-label">Host Address</label> <label for="host_id_new" class="form-label">Host Address</label>
<div class="input-group has-validation"> <div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-hash"></i></span> <span class="input-group-text"><i class="bi bi-hash"></i></span>
<input type="text" class="form-control text-end @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> <input type="text" class="form-control text-end @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 data-1p-ignore>
<span class="input-group-text">/0.0</span> <span class="input-group-text">/0.0</span>
<span class="invalid-feedback" role="alert"> <span class="invalid-feedback" role="alert">
@error('host_id_new') @error('host_id_new')
@ -246,6 +200,9 @@
if (! $('#sec-level').hasClass('d-none')) if (! $('#sec-level').hasClass('d-none'))
$('#sec-level').addClass('d-none') $('#sec-level').addClass('d-none')
if (! this.value)
return false;
var icon = $(this).parent().find('i'); var icon = $(this).parent().find('i');
icon.addClass('spinner-grow spinner-grow-sm'); icon.addClass('spinner-grow spinner-grow-sm');

View File

@ -1,13 +1,15 @@
<!-- $o=System::class -->
@use(Carbon\Carbon) @use(Carbon\Carbon)
@use(Carbon\CarbonInterface) @use(Carbon\CarbonInterface)
@use(Illuminate\Support\Facades\Gate)
@use(App\Classes\FTN\Packet) @use(App\Classes\FTN\Packet)
@use(App\Models\Mailer) @use(App\Models\Mailer)
@use(App\Models\User) @use(App\Models\User)
<!-- $o=System::class -->
<div class="row"> <div class="row">
<div class="col-xl-9 col-12"> <div class="col-xl-9 col-12">
@can('admin',$o) <div class="row pt-0">
<div class="row pt-0"> @can('admin')
<div class="col-12"> <div class="col-12">
<h4 class="mb-0 pb-2">System Users</h4> <h4 class="mb-0 pb-2">System Users</h4>
@ -19,7 +21,7 @@
<span class="input-group-text"><i class="bi bi-people-fill"></i></span> <span class="input-group-text"><i class="bi bi-people-fill"></i></span>
<select style="width: 80%;" class="form-select @error('users') is-invalid @enderror" id="users" name="users[]"> <select style="width: 80%;" class="form-select @error('users') is-invalid @enderror" id="users" name="users[]">
<option value="">&nbsp;</option> <option value="">&nbsp;</option>
@foreach (User::orderBy('name')->active()->get() as $uo) @foreach (User::select(['id','name','email'])->orderBy('name')->active()->get() as $uo)
<option value="{{ $uo->id }}" @selected(in_array($uo->id,old('users',$o->users->pluck('id')->toArray())))>{{ $uo->name }} <small>({{ $uo->email }})</small></option> <option value="{{ $uo->id }}" @selected(in_array($uo->id,old('users',$o->users->pluck('id')->toArray())))>{{ $uo->name }} <small>({{ $uo->email }})</small></option>
@endforeach @endforeach
</select> </select>
@ -33,10 +35,10 @@
</div> </div>
</div> </div>
</div> </div>
</div> @endcan
@endcan </div>
<div class="row pt-4"> <div class="row @can('admin')pt-4 @else pt-0 @endcannot">
<div class="col-12"> <div class="col-12">
<h4 class="mb-0 pb-2">System Details</h4> <h4 class="mb-0 pb-2">System Details</h4>
@ -46,9 +48,7 @@
<label for="name" class="form-label">BBS Name</label> <label for="name" class="form-label">BBS Name</label>
<div class="input-group has-validation"> <div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-pc"></i></span> <span class="input-group-text"><i class="bi bi-pc"></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($action,$o)readonly @endcannot autofocus> <input type="text" class="form-control @error('name') is-invalid @enderror" id="name" placeholder="Name" name="name" value="{{ old('name',$o->name) }}" required @cannot($action,$o)readonly @endcannot autofocus autocomplete="off" data-1p-ignore>
<span id="search-icon" style="width: 0;"><i style="border-radius: 50%;" class="spinner-border spinner-border-sm text-dark d-none"></i></span>
<div id="system_search_results"></div>
<span class="invalid-feedback" role="alert"> <span class="invalid-feedback" role="alert">
@error('name') @error('name')
{{ $message }} {{ $message }}
@ -116,7 +116,7 @@
<label for="address" class="form-label">Mailer Internet Hostname</label> <label for="address" class="form-label">Mailer Internet Hostname</label>
<div class="input-group has-validation"> <div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-globe"></i></span> <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($action,$o)readonly @endcannot> <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($action,$o)readonly @endcannot data-1p-ignore>
<span class="invalid-feedback" role="alert"> <span class="invalid-feedback" role="alert">
@error('address') @error('address')
{{ $message }} {{ $message }}
@ -174,20 +174,7 @@
<!-- Mail Packet --> <!-- Mail Packet -->
<div class="col-4"> <div class="col-4">
<label for="pkt_type" class="form-label">Mail Packet</label> <x-form.select name="pkt_type" icon="bi-ui-radios" label="Mail Packet" feedback="Set a packet type" :value="$o->pkt_type ?: config('fido.packet_default')" :options="collect(Packet::PACKET_TYPES)->map(fn($item,$key)=>['id'=>$key,'value'=>$key])" required="true" :disabled="Gate::denies('update_nn',$o)"/>
<div class="input-group">
<span class="input-group-text"><i class="bi bi-ui-radios"></i></span>
<select class="form-select @error('pkt_type') is-invalid @enderror" id="pkt_type" name="pkt_type" @cannot($action,$o)disabled @endcannot>
@foreach (Packet::PACKET_TYPES as $type => $class)
<option value="{{ $type }}" @if(old('pkt_type',$o->pkt_type ?: config('fido.packet_default')) === $type)selected @endif>{{ $type }}</option>
@endforeach
</select>
<span class="invalid-feedback" role="alert">
@error('pkt_type')
{{ $message }}
@enderror
</span>
</div>
</div> </div>
<!-- Packet Msgs --> <!-- Packet Msgs -->
@ -214,17 +201,9 @@
<div class="row pt-0"> <div class="row pt-0">
<div class="col-4"> <div class="col-4">
<label for="method" class="form-label">Connection Method</label> <x-form.select name="method" icon="bi-wifi" label="Connection Method" :value="$o->method" :options="collect([['id'=>23,'value'=>'Telnet'],['id'=>22,'value'=>'SSH'],['id'=>519,'value'=>'Rlogin']])" :disabled="Gate::denies('update_nn',$o)"/>
<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($action,$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>
<div class="col-3"> <div class="col-3">
<label for="method" class="form-label">Port</label> <label for="method" class="form-label">Port</label>
<div class="input-group"> <div class="input-group">
@ -303,28 +282,30 @@
<div class="row"> <div class="row">
<div class="col-12"> <div class="col-12">
<div class="row p-0"> <div class="row p-0">
@can('update_nn',$o) @if($o->exists)
<div class="col-6"> @can('update_nn',$o)
<label for="autohold" class="form-label">Auto Hold</label> <div class="col-6">
<div class="input-group"> <label for="autohold" class="form-label">Auto Hold</label>
<button id="autohold" @class(['btn','btn-warning'=>$o->autohold,'btn-outline-success'=>(! $o->autohold)])><i @class(['bi-toggle-on'=>$o->autohold,'bi-toggle-off'=>(! $o->autohold)])></i></button> <div class="input-group">
<button id="autohold" @class(['btn','btn-warning'=>$o->autohold,'btn-outline-success'=>(! $o->autohold)])><i @class(['bi-toggle-on'=>$o->autohold,'bi-toggle-off'=>(! $o->autohold)])></i></button>
</div>
</div> </div>
</div>
<!-- @todo This is only relevant for uplinks, so hide it if this system isnt an uplink --> <!-- @todo This is only relevant for uplinks, so hide it if this system isnt an uplink -->
<div class="col-6 @if((old('pollmode') === "0") || is_null($o->pollmode))d-none @endif" id="heartbeat_option"> <div class="col-6 @if((old('pollmode') === "0") || is_null($o->pollmode))d-none @endif" id="heartbeat_option">
<label for="heartbeat" class="form-label">Heartbeat <i class="bi bi-info-circle" title="Attempt contact after last seen"></i></label> <label for="heartbeat" class="form-label">Heartbeat <i class="bi bi-info-circle" title="Attempt contact after last seen"></i></label>
<div class="input-group has-validation"> <div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-hourglass-bottom"></i></span> <span class="input-group-text"><i class="bi bi-hourglass-bottom"></i></span>
<input type="text" class="form-control text-end @error('heartbeat') is-invalid @enderror" id="heartbeat" placeholder="Hrs" name="heartbeat" value="{{ old('heartbeat',$o->heartbeat) }}"> <input type="text" class="form-control text-end @error('heartbeat') is-invalid @enderror" id="heartbeat" placeholder="Hrs" name="heartbeat" value="{{ old('heartbeat',$o->heartbeat) }}">
<span class="invalid-feedback" role="alert"> <span class="invalid-feedback" role="alert">
@error('heartbeat') @error('heartbeat')
{{ $message }} {{ $message }}
@enderror @enderror
</span> </span>
</div>
</div> </div>
</div> @endcan
@endcan @endif
</div> </div>
@if(! is_null($o->pollmode)) @if(! is_null($o->pollmode))
@ -418,7 +399,7 @@
</div> </div>
</div> </div>
@can('admin',$o) @can('admin')
<div class="row"> <div class="row">
<!-- Notes --> <!-- Notes -->
<div class="col-12"> <div class="col-12">
@ -444,15 +425,15 @@
</div> </div>
</div> </div>
@section('page-css')
@css('select2')
@append
@section('page-scripts') @section('page-scripts')
@js('select2')
<script type="text/javascript"> <script type="text/javascript">
$(document).ready(function() { $(document).ready(function() {
$('#users').select2({ $('#users').select2({
theme: 'bootstrap-5',
dropdownAutoWidth: true,
width: 'style',
allowClear: true,
placeholder: '',
@cannot('admin')disabled: true @endcannot @cannot('admin')disabled: true @endcannot
/*multiple: true*/ /*multiple: true*/
}); });
@ -466,57 +447,59 @@
$('#poll_hold').on('click',function() { $('#poll_hold').on('click',function() {
$('#heartbeat_option').addClass('d-none'); $('#heartbeat_option').addClass('d-none');
}) })
$("#autohold").on('click',function(item) { @if($o->exists)
var that = $(this) $("#autohold").on('click',function(item) {
var icon = that.find('i'); var that = $(this)
var icon = that.find('i');
if (icon.hasClass('bi-toggle-on')) { if (icon.hasClass('bi-toggle-on')) {
$.ajax({ $.ajax({
url: '/system/api/autohold/off', url: '/system/api/autohold/off',
type: 'POST', type: 'POST',
dataType: 'json', dataType: 'json',
data : {id: {{ $o->id }}}, data : {id: {{ $o->id }}},
beforeSend: function() { beforeSend: function() {
icon.addClass('spinner-grow spinner-grow-sm') icon.addClass('spinner-grow spinner-grow-sm')
}, },
complete: function() { complete: function() {
icon.removeClass('spinner-grow spinner-grow-sm') icon.removeClass('spinner-grow spinner-grow-sm')
}, },
success: function(data) { success: function(data) {
icon.removeClass('bi-toggle-on') icon.removeClass('bi-toggle-on')
.addClass('bi-toggle-off') .addClass('bi-toggle-off')
that.removeClass('btn-warning') that.removeClass('btn-warning')
.addClass('btn-outline-success') .addClass('btn-outline-success')
}, },
cache: false cache: false
}); });
} else { } else {
$.ajax({ $.ajax({
url: '/system/api/autohold/on', url: '/system/api/autohold/on',
type: 'POST', type: 'POST',
dataType: 'json', dataType: 'json',
data : {id: {{ $o->id }}}, data : {id: {{ $o->id }}},
beforeSend: function() { beforeSend: function() {
icon.addClass('spinner-grow spinner-grow-sm') icon.addClass('spinner-grow spinner-grow-sm')
}, },
complete: function() { complete: function() {
icon.removeClass('spinner-grow spinner-grow-sm') icon.removeClass('spinner-grow spinner-grow-sm')
}, },
success: function(data) { success: function(data) {
icon.removeClass('bi-toggle-off') icon.removeClass('bi-toggle-off')
.addClass('bi-toggle-on'); .addClass('bi-toggle-on');
that.removeClass('btn-outline-success') that.removeClass('btn-outline-success')
.addClass('btn-warning') .addClass('btn-warning')
}, },
cache: false cache: false
}); });
} }
return false; return false;
}) })
@endif
}) })
</script> </script>
@append @append

View File

@ -1,16 +1,15 @@
@use(App\Models\System)
@extends('layouts.app') @extends('layouts.app')
@section('htmlheader_title') @section('htmlheader_title')
Register System Register System
@endsection @endsection
@php
use App\Models\System;
@endphp
@section('content') @section('content')
<form class="needs-validation" method="post" autocomplete="off" novalidate> <form method="POST" autocomplete="off">
@csrf @csrf
<input type="hidden" name="action" value="register">
<div class="row"> <div class="row">
<div class="col-12"> <div class="col-12">
@ -27,13 +26,13 @@ use App\Models\System;
->whereRaw('id NOT IN (SELECT system_id FROM "system_user")') ->whereRaw('id NOT IN (SELECT system_id FROM "system_user")')
->cursor()) ->cursor())
<x-form.select id="system" name="id" icon="bi-laptop-fill" label="BBS Name" placeholder="See if your BBS exists, otherwise add it" feedback="BBS Name is required" helper="Enter your BBS name and press NEXT" :addvalues="true" :options="$options->map(fn($item,$key)=>['id'=>$item->id,'value'=>$item->name])" /> <x-form.select name="system_id" icon="bi-laptop-fill" label="BBS Name" placeholder="See if your BBS exists, otherwise add it" feedback="BBS Name is required" helper="Enter your BBS name and press NEXT" :addvalues="true" :options="$options->map(fn($item,$key)=>['id'=>$item->id,'value'=>$item->name])" />
</div> </div>
</div> </div>
<div class="row"> <div class="row">
<div class="col-12 pb-2"> <div class="col-12 pb-2">
<button type="button" name="submit" class="btn btn-success">Next</button><span id="next" class="m-2"><i class="spinner-border spinner-border-sm text-light d-none"></i></span> <button type="submit" class="btn btn-success">Next</button><span id="next" class="m-2"><i class="spinner-border spinner-border-sm text-light d-none"></i></span>
</div> </div>
</div> </div>
</div> </div>
@ -41,104 +40,4 @@ use App\Models\System;
</div> </div>
</div> </div>
</form> </form>
@endsection
<div class="modal fade" id="no-auth" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header bg-danger">
<h5 class="modal-title">ERROR: No authorisation</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<p>It appears that you are not allowed to create this entry.</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
@endsection
@section('page-scripts')
<script type='text/javascript'>
var system_id;
var noauth = new bootstrap.Modal(document.getElementById('no-auth'), {});
function validation(item,message) {
var attr = $('input[id='+item+']');
attr.addClass('is-invalid')
attr.parent().find('.invalid-feedback').empty().append(message);
}
/**
* We have selected a BBS from the link/register form, and it's either a new entry or an existing one
* @param icon
*/
function getform(icon) {
$.ajax({
url : '{{ url('user/system/register') }}',
type : 'POST',
data : { system_id: system_id,name: $('#system').val(),action: 'register',old: {!! json_encode(old()) !!} },
dataType : 'json',
async : true,
cache : false,
beforeSend : function() {
if (icon)
icon.toggleClass('d-none');
},
complete : function(data) {
switch (data.status) {
case 200:
// if json is null, means no match, won't do again.
if(data.responseText===null || (data.responseText.length===0)) return;
$('#create').empty().append(data.responseText);
@if($errors->count())
@foreach($errors->keys() as $key)
validation('{{ $key }}','{{ $errors->first($key) }}');
@endforeach
@endif
break;
case 403:
if (icon)
icon.toggleClass('d-none');
noauth.show();
break;
case 419:
location.reload();
break;
case 422:
validation('name',data.responseJSON.errors.name[0]);
if (icon)
icon.toggleClass('d-none');
break;
default:
return false;
}
}
})
}
if ({{ old('submit') === 'create' ? 'true' : 'false' }}) {
getform();
}
$(document).ready(function() {
$('button[name=submit]').on('click',function() {
icon = $(this).parent().find('i');
if (! $('#system').val())
return;
getform(icon);
})
});
</script>
@append

View File

@ -0,0 +1,57 @@
<!-- $so=System::class -->
@use(App\Models\System)
@extends('layouts.app')
@section('htmlheader_title')
Register System
@endsection
@section('content')
@if(! $so->address)
<h3 class="pt-2">Enable to complete registration</h3>
<p>The system you selected <strong class="highlight">{{ $so->name }}</strong> doesnt have mailer details, please contact that system administration to update those details first</p>
@else
<h3 class="pt-2">System Details:</h3>
<table class="monotable">
<tr>
<th>System</th>
<th>{{ $so->name }}</th>
</tr>
<tr>
<th>Sysop</th>
<th>{{ $so->sysop }}</th>
</tr>
<tr>
<th>Location</th>
<th>{{ $so->location }}</th>
</tr>
<tr>
<th>Networks</th>
<th>{{ $so->akas->pluck('ftn')->join(', ') }}</th>
</tr>
<tr>
<th>Address</th>
<th>{{ $so->access_mailer }}</th>
</tr>
</table>
<p>If the details are above are not correct, then please contact the (ZC) to have them corrected first.</p>
<p>Otherwise, if all is good, we'll send a netmail to <strong class="highlight">{{ $so->sysop }}</strong> at <strong class="highlight">{{ $so->access_mailer }}</strong></p> with further details.
<form class="needs-validation" method="post" autocomplete="off" action="{{ url('user/system/link') }}" novalidate>
@csrf
<input type="hidden" name="system_id" value="{{ $so->id }}">
<input type="hidden" name="name" value="{{ $so->name }}">
<div class="row pb-2">
<div class="col-12">
<input type="submit" name="action" class="btn btn-success" value="Link">
</div>
</div>
</form>
@endif
@endsection

View File

@ -1,41 +0,0 @@
<!-- $o = System::class -->
<h3>System Details:</h3>
<table class="monotable">
<tr>
<th>System</th>
<th>{{ $o->name }}</th>
</tr>
<tr>
<th>Sysop</th>
<th>{{ $o->sysop }}</th>
</tr>
<tr>
<th>Location</th>
<th>{{ $o->location }}</th>
</tr>
<tr>
<th>Networks</th>
<th>{{ $o->akas->pluck('ftn')->join(', ') }}</th>
</tr>
<tr>
<th>Address</th>
<th>{{ $o->access_mailer }}</th>
</tr>
</table>
<p>If the details are above are not correct, then please contact the (ZC) to have them corrected first.</p>
<p>Otherwise, if all is good, we'll send a netmail to <strong class="highlight">{{ $o->sysop }}</strong> at <strong class="highlight">{{ $o->access_mailer }}</strong></p> with further details.
<form class="needs-validation" method="post" autocomplete="off" action="{{ url('user/system/link') }}" novalidate>
@csrf
<input type="hidden" name="system_id" value="{{ $o->id }}">
<input type="hidden" name="name" value="{{ $o->name }}">
<div class="row pb-2">
<div class="col-12">
<input type="submit" name="action" class="btn btn-success" value="Link">
</div>
</div>
</form>

View File

@ -135,7 +135,9 @@ Route::middleware(['auth','verified','activeuser'])->group(function () {
Route::view('user/system/register','user.system.register'); Route::view('user/system/register','user.system.register');
Route::post('user/system/register',[SystemController::class,'register']); Route::post('user/system/register',[SystemController::class,'register']);
Route::match(['post'],'user/system/link',[SystemController::class,'system_link']); Route::view('user/system/register_confirm/{so}','user.system.register_confirm')
->where('so','[0-9]+');
Route::post('user/system/link',[SystemController::class,'system_link']);
/* ZONE PATHS */ /* ZONE PATHS */
Route::view('zone','zone.home'); Route::view('zone','zone.home');