Compare commits

...

3 Commits

Author SHA1 Message Date
f13d3396ce Update job:list, and change "subject" to "jobname"
All checks were successful
Create Docker Image / Build Docker Image (x86_64) (push) Successful in 40s
Create Docker Image / Build Docker Image (arm64) (push) Successful in 1m41s
Create Docker Image / Final Docker Image Manifest (push) Successful in 10s
2024-05-21 21:11:10 +10:00
0c4c2f8cf5 Update SocketClient to support raw IP addresses 2024-05-21 21:11:10 +10:00
04aa86b6ee Security update enabling update_nn to edit system details 2024-05-21 21:11:10 +10:00
14 changed files with 73 additions and 57 deletions

View File

@ -201,10 +201,16 @@ final class SocketClient {
$sort = collect(['AAAA','A']); $sort = collect(['AAAA','A']);
// We only look at AAAA/A records if (filter_var($address,FILTER_VALIDATE_IP))
$resolved = collect(dns_get_record($address,DNS_AAAA|DNS_A)) $resolved = collect([[
->filter(function($item) use ($sort) { return $sort->search(Arr::get($item,'type')) !== FALSE; }) (($x=filter_var($address,FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) ? 'ipv6' : 'ip')=>$address,
->sort(function($item) use ($sort) { return $sort->search(Arr::get($item,'type')); }); 'type'=>$x ? 'AAAA' : 'A'
]]);
else
// We only look at AAAA/A records
$resolved = collect(dns_get_record($address,DNS_AAAA|DNS_A))
->filter(function($item) use ($sort) { return $sort->search(Arr::get($item,'type')) !== FALSE; })
->sort(function($item) use ($sort) { return $sort->search(Arr::get($item,'type')); });
if (! $resolved->count()) if (! $resolved->count())
throw new SocketException(SocketException::CANT_CONNECT,sprintf('%s doesnt resolved to an IPv4/IPv6 address',$address)); throw new SocketException(SocketException::CANT_CONNECT,sprintf('%s doesnt resolved to an IPv4/IPv6 address',$address));

View File

@ -39,7 +39,7 @@ class JobList extends Command
$o->uuid, $o->uuid,
$o->id, $o->id,
$o->display_name, $o->display_name,
$o->command->subject, $o->command->jobname,
$o->attempts,$o->maxTries, $o->attempts,$o->maxTries,
$o->available_at ?: '-', $o->available_at ?: '-',
$o->attempts ? sprintf(' (Created:%s)',$o->created_at) : '' $o->attempts ? sprintf(' (Created:%s)',$o->created_at) : ''

View File

@ -16,7 +16,7 @@ use Illuminate\Support\Facades\Notification;
use Illuminate\Support\ViewErrorBag; use Illuminate\Support\ViewErrorBag;
use App\Classes\FTN\Message; use App\Classes\FTN\Message;
use App\Http\Requests\{AddressMerge,AreafixRequest,SystemEchoareaRequest,SystemRegister,SystemSessionRequest}; use App\Http\Requests\{AddressMerge,AreafixRequest,SystemEchoareaRequest,SystemRegisterRequest,SystemSessionRequest};
use App\Jobs\AddressPoll; use App\Jobs\AddressPoll;
use App\Models\{Address,Echoarea,Echomail,Filearea,Netmail,Setup,System,Zone}; use App\Models\{Address,Echoarea,Echomail,Filearea,Netmail,Setup,System,Zone};
use App\Notifications\Netmails\AddressLink; use App\Notifications\Netmails\AddressLink;
@ -29,13 +29,18 @@ class SystemController extends Controller
/** /**
* Add or edit a node * Add or edit a node
*/ */
public function add_edit(SystemRegister $request,System $o) public function add_edit(SystemRegisterRequest $request, System $o)
{ {
if ($request->post()) { if ($request->validated()) {
foreach (['name','location','sysop','hold','phone','address','port','active','method','notes','zt_id','pkt_type','heartbeat'] as $key) foreach (['name','location','phone','address','port','active','method','pkt_type'] as $key)
$o->{$key} = $request->post($key); $o->{$key} = $request->validated($key);
switch ($request->post('pollmode')) { // Sometimes items
foreach (['sysop','hold','notes','zt_id','heartbeat'] as $key)
if ($request->validated($key))
$o->{$key} = $request->validated($key);
switch ($request->validated('pollmode')) {
case 1: $o->pollmode = FALSE; break; case 1: $o->pollmode = FALSE; break;
case 2: $o->pollmode = TRUE; break; case 2: $o->pollmode = TRUE; break;
default: $o->pollmode = NULL; default: $o->pollmode = NULL;
@ -49,9 +54,9 @@ class SystemController extends Controller
->transform(function($item) { $item['active'] = Arr::get($item,'active',FALSE); return $item; }); ->transform(function($item) { $item['active'] = Arr::get($item,'active',FALSE); return $item; });
$o->mailers()->sync($mailers); $o->mailers()->sync($mailers);
if ($request->post('users')) { if ($request->validated('users')) {
if (array_filter($request->post('users'),function($item) { return $item; })) if (array_filter($request->validated('users'),function($item) { return $item; }))
$o->users()->sync($request->post('users')); $o->users()->sync($request->validated('users'));
else else
$o->users()->detach(); $o->users()->detach();
} }
@ -62,7 +67,7 @@ class SystemController extends Controller
$o->load(['addresses.zone.domain','addresses.nodes_hub','addresses.system','sessions.domain','sessions.systems']); $o->load(['addresses.zone.domain','addresses.nodes_hub','addresses.system','sessions.domain','sessions.systems']);
return view('system.addedit') return view('system.addedit')
->with('action',$o->exists ? 'update' : 'create') ->with('action',$o->exists ? 'update_nn' : 'create')
->with('o',$o); ->with('o',$o);
} }
@ -767,7 +772,7 @@ class SystemController extends Controller
/** /**
* Register a system, or link to an existing system * Register a system, or link to an existing system
*/ */
public function register(SystemRegister $request) public function register(SystemRegisterRequest $request)
{ {
// Step 1, show the user a form to select an existing defined system // Step 1, show the user a form to select an existing defined system
if ($request->isMethod('GET')) if ($request->isMethod('GET'))

View File

@ -10,8 +10,7 @@ use Illuminate\Validation\Rule;
use App\Classes\FTN\Packet; use App\Classes\FTN\Packet;
use App\Models\{Setup,System}; use App\Models\{Setup,System};
// @todo rename to SystemRegisterRequest class SystemRegisterRequest extends FormRequest
class SystemRegister extends FormRequest
{ {
private System $so; private System $so;
@ -73,7 +72,7 @@ class SystemRegister extends FormRequest
],($so && $so->exists) ? [ ],($so && $so->exists) ? [
'users' => 'nullable|array|min:1|max:2', 'users' => 'nullable|array|min:1|max:2',
'active' => 'required|boolean', 'active' => 'required|boolean',
'hold' => 'required|boolean', 'hold' => 'sometimes|boolean',
'pollmode' => 'required|integer|min:0|max:2', 'pollmode' => 'required|integer|min:0|max:2',
'heartbeat' => 'nullable|integer|min:0|max:48', 'heartbeat' => 'nullable|integer|min:0|max:48',
] : [])); ] : []));

View File

@ -50,7 +50,7 @@ class AddressPoll implements ShouldQueue, ShouldBeUnique
case 'address': case 'address':
return $this->ao; return $this->ao;
case 'subject': case 'jobname':
return $this->ao->ftn; return $this->ao->ftn;
default: default:
@ -125,7 +125,7 @@ class AddressPoll implements ShouldQueue, ShouldBeUnique
} }
} catch (SocketException $e) { } catch (SocketException $e) {
Log::error(sprintf('%s:! Unable to connect to [%s]: %s',self::LOGKEY,$this->ao->ftn,$e->getMessage())); Log::error(sprintf('%s:! SocketException Unable to connect to [%s]: %s',self::LOGKEY,$this->ao->ftn,$e->getMessage()));
break; break;
} catch (\ErrorException $e) { } catch (\ErrorException $e) {

View File

@ -47,7 +47,7 @@ class EchoareaImport implements ShouldQueue
public function __get($key): mixed public function __get($key): mixed
{ {
switch ($key) { switch ($key) {
case 'subject': case 'jobname':
return sprintf('%s-%s',$this->do->name,$this->file); return sprintf('%s-%s',$this->do->name,$this->file);
default: default:

View File

@ -47,7 +47,7 @@ class FileareaImport implements ShouldQueue
public function __get($key): mixed public function __get($key): mixed
{ {
switch ($key) { switch ($key) {
case 'subject': case 'jobname':
return sprintf('%s-%s',$this->do->name,$this->file); return sprintf('%s-%s',$this->do->name,$this->file);
default: default:

View File

@ -41,8 +41,9 @@ class MessageProcess implements ShouldQueue
public function __get($key): mixed public function __get($key): mixed
{ {
switch ($key) { switch ($key) {
case 'subject': case 'jobname':
return sprintf('%s-%s-%s',$this->pktname,$this->mo->set->get('set_sender')->ftn,$this->mo->msgid); $mo = unserialize($this->mo);
return sprintf('%s-%s-%s',$mo->set->get('set_pkt'),$mo->set->get('set_sender')->ftn,$mo->msgid);
default: default:
return NULL; return NULL;

View File

@ -58,7 +58,7 @@ class NodelistImport implements ShouldQueue
public function __get($key): mixed public function __get($key): mixed
{ {
switch ($key) { switch ($key) {
case 'subject': case 'jobname':
return sprintf('%s-%s',$this->domain?->name,is_object($this->file) ? $this->file->name : $this->file); return sprintf('%s-%s',$this->domain?->name,is_object($this->file) ? $this->file->name : $this->file);
default: default:

View File

@ -44,7 +44,7 @@ class PacketProcess implements ShouldQueue
public function __get($key): mixed public function __get($key): mixed
{ {
switch ($key) { switch ($key) {
case 'subject': case 'jobname':
return $this->filename; return $this->filename;
default: default:

View File

@ -42,7 +42,7 @@ class TicProcess implements ShouldQueue
public function __get($key): mixed public function __get($key): mixed
{ {
switch ($key) { switch ($key) {
case 'subject': case 'jobname':
return sprintf('%s %s',$this->do?->name,$this->file); return sprintf('%s %s',$this->do?->name,$this->file);
default: default:

View File

@ -1,12 +1,12 @@
@php @php
use App\Models\Address; use App\Models\Address;
@endphp @endphp
<!-- $o=System::class --> <!-- $o=System::class -->
@extends('layouts.app') @extends('layouts.app')
@section('htmlheader_title') @section('htmlheader_title')
@can('admin',$o) @if($o->exists) Update @else Add @endif @endcan System @can('update_nn',$o) @if($o->exists) Update @else Add @endif @endcan System
@endsection @endsection
@section('content') @section('content')
@ -21,6 +21,7 @@
<p>This system is the ZC for the following zones: <strong class="highlight">{!! $o->zcs->sortBy('zone_id')->map(function($item) { return sprintf('%d@%s',$item->zone_id,$item->domain->name); })->join('</strong>, <strong class="highlight">') !!} </strong></p> <p>This system is the ZC for the following zones: <strong class="highlight">{!! $o->zcs->sortBy('zone_id')->map(function($item) { return sprintf('%d@%s',$item->zone_id,$item->domain->name); })->join('</strong>, <strong class="highlight">') !!} </strong></p>
@endif @endif
@include('widgets.error')
<div class="accordion" id="accordion_homepage"> <div class="accordion" id="accordion_homepage">
@if ($o->exists) @if ($o->exists)
<!-- System --> <!-- System -->
@ -163,8 +164,8 @@
<span class="btn btn-sm btn-danger" role="alert" style="text-align: left;"> <span class="btn btn-sm btn-danger" role="alert" style="text-align: left;">
{!! $message !!} {!! $message !!}
</span> </span>
</div>
</div> </div>
</div>
@enderror @enderror
@can('admin',$o) @can('admin',$o)

View File

@ -1,3 +1,4 @@
<!-- $o=System::class -->
<form class="needs-validation" method="post" novalidate> <form class="needs-validation" method="post" novalidate>
@csrf @csrf
<input type="hidden" name="system_id" value="{{ $o->id }}"> <input type="hidden" name="system_id" value="{{ $o->id }}">
@ -5,7 +6,7 @@
<div class="row pt-0"> <div class="row pt-0">
<div class="col-12"> <div class="col-12">
<div class="greyframe titledbox shadow0xb0"> <div class="greyframe titledbox shadow0xb0">
<h2 class="cap">@can('update',$o) @if($o->exists) Update @else Add @endif @endif System</h2> <h2 class="cap">@can($action,$o) @if($o->exists) Update @else Add @endif @endif System</h2>
@include('system.widget.system') @include('system.widget.system')
</div> </div>

View File

@ -1,9 +1,9 @@
@php @php
use App\Classes\FTN\Packet; use App\Classes\FTN\Packet;
use App\Models\{Mailer,User}; use App\Models\{Mailer,User};
@endphp @endphp
<!-- $o = System::class --> <!-- $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) @can('admin',$o)
@ -46,7 +46,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('update',$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>
<span id="search-icon" style="width: 0;"><i style="border-radius: 50%;" class="spinner-border spinner-border-sm text-dark d-none"></i></span> <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> <div id="system_search_results"></div>
<span class="invalid-feedback" role="alert"> <span class="invalid-feedback" role="alert">
@ -227,7 +227,7 @@
<div class="row"> <div class="row">
<!-- Active --> <!-- Active -->
<div class="col-6"> <div class="col-6">
@can('update',$o) @can($action,$o)
<label for="active" class="form-label">Active</label> <label for="active" class="form-label">Active</label>
<div class="input-group"> <div class="input-group">
<div class="btn-group" role="group"> <div class="btn-group" role="group">
@ -245,7 +245,7 @@
<div class="row"> <div class="row">
<!-- Hold --> <!-- Hold -->
<div class="col-6"> <div class="col-6">
@can('update',$o) @can('admin',$o)
<label for="hold" class="form-label">Hold Mail <i class="bi bi-info-circle" title="Dont give the node any mail regardless of poll mode"></i></label> <label for="hold" class="form-label">Hold Mail <i class="bi bi-info-circle" title="Dont give the node any mail regardless of poll mode"></i></label>
<div class="input-group"> <div class="input-group">
<div class="btn-group" role="group"> <div class="btn-group" role="group">
@ -263,7 +263,7 @@
<div class="row"> <div class="row">
<!-- Poll Mode --> <!-- Poll Mode -->
<div class="col-12"> <div class="col-12">
@can('update',$o) @can($action,$o)
<label for="pollmode" class="form-label">Poll Mode <i class="bi bi-info-circle" title="Poll node when mail available, poll on a schedule or hold mail for collection"></i></label> <label for="pollmode" class="form-label">Poll Mode <i class="bi bi-info-circle" title="Poll node when mail available, poll on a schedule or hold mail for collection"></i></label>
<div class="input-group has-validation"> <div class="input-group has-validation">
<div class="btn-group @error('pollmode') is-invalid @enderror" role="group"> <div class="btn-group @error('pollmode') is-invalid @enderror" role="group">
@ -287,11 +287,18 @@
</div> </div>
<div class="row"> <div class="row">
<!-- @todo This is only relevant for uplinks, so hide it if this system isnt an uplink --> <div class="col-12">
<div class="col-12 @if((old('pollmode') === "0") || is_null($o->pollmode))d-none @endif" id="heartbeat_option"> <div class="row p-0">
@can('admin',$o) <div class="col-6">
<div class="row p-0"> <label for="autohold" class="form-label">Auto Hold</label>
<div class="col-6"> <div class="input-group">
<button id="autohold" @class(['btn','btn-danger'=>$o->autohold,'btn-success'=>(! $o->autohold)])><i @class(['bi-toggle-on'=>$o->autohold,'bi-toggle-off'=>(! $o->autohold)])></i></button>
</div>
</div>
<!-- @todo This is only relevant for uplinks, so hide it if this system isnt an uplink -->
@can('admin',$o)
<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>
@ -303,18 +310,15 @@
</span> </span>
</div> </div>
</div> </div>
@endcan
<div class="col-6">
<label for="passkey" class="form-label">Auto Hold</label>
<button id="autohold" @class(['btn','btn-danger'=>$o->autohold,'btn-success'=>(! $o->autohold)])><i @class(['bi-toggle-on'=>$o->autohold,'bi-toggle-off'=>(! $o->autohold)])></i></button>
</div>
</div>
@endcan
@if (! is_null($o->pollmode)) </div>
@if(! is_null($o->pollmode))
<div class="row"> <div class="row">
<div class="col-12 bg-secondary rounded p-2 small"> <div class="col-12 bg-secondary rounded p-2 small">
@if($job = $o->poll()) @if($job=$o->poll())
<div class="row p-0"> <div class="row p-0">
<div class="col-4 text-dark"> <div class="col-4 text-dark">
@if($job->attempts)Last: @else Scheduled: @endif @if($job->attempts)Last: @else Scheduled: @endif
@ -333,7 +337,7 @@
</div> </div>
</div> </div>
@if ($job->attempts) @if($job->attempts)
<div class="row"> <div class="row">
<div class="col-4 text-dark"> <div class="col-4 text-dark">
Next: Next:
@ -363,7 +367,7 @@
</div> </div>
</div> </div>
@if ($o->heartbeat) @if($o->heartbeat)
<div class="row"> <div class="row">
<div class="col-4 text-dark"> <div class="col-4 text-dark">
Next Heartbeat: Next Heartbeat:
@ -381,7 +385,7 @@
</div> </div>
<div class="col-8"> <div class="col-8">
<strong class="highlight"> <strong class="highlight">
@if ($job) Queued @if($job) Queued
@elseif ($o->autohold)Auto Hold @elseif ($o->autohold)Auto Hold
@else @else
@switch($o->pollmode) @switch($o->pollmode)
@ -416,7 +420,7 @@
@if($o->exists) @if($o->exists)
@can($action,$o) @can($action,$o)
<a href="{{ url('system') }}" class="btn btn-danger">Cancel</a> <a href="{{ url('system') }}" class="btn btn-danger">Cancel</a>
<button type="submit" name="submit" class="btn btn-success float-end">@if ($o->exists)Save @else Add @endif</button> <button type="submit" name="submit" class="btn btn-success float-end">@if($o->exists)Save @else Add @endif</button>
@else @else
<input type="hidden" name="system_id" value="{{ $o->id }}"> <input type="hidden" name="system_id" value="{{ $o->id }}">
<span><small><strong>NOTE:</strong> You'll be able to update these details after registration is completed.</small></span> <span><small><strong>NOTE:</strong> You'll be able to update these details after registration is completed.</small></span>
@ -449,7 +453,6 @@
}) })
$('#poll_hold').on('click',function() { $('#poll_hold').on('click',function() {
$('#heartbeat_option').addClass('d-none'); $('#heartbeat_option').addClass('d-none');
console.log('hold');
}) })
$("#autohold").on('click',function(item) { $("#autohold").on('click',function(item) {
var that = $(this) var that = $(this)