Added tool to list node addresses and the address we use,

Fix address edit which reactivated the address,
Fix correct icons when using address merge,
We only advertise validated addresses and use validated addresses for routing,
Show our address on known AKA screen
This commit is contained in:
Deon George 2025-04-14 23:09:41 +10:00
parent 1656087ded
commit b59317871a
6 changed files with 143 additions and 17 deletions

View File

@ -0,0 +1,64 @@
<?php
namespace App\Console\Commands\Debug;
use Illuminate\Console\Command;
use App\Models\Address;
class AddressCheckNode extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'debug:address:check:nodes'
.' {ftn? : FTN}'
.' {--N|node : Node Order}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Check all addresses we use for nodes';
/**
* Execute the console command.
*
* @return int
* @throws \Exception
*/
public function handle(): int
{
$ao = NULL;
if ($this->argument('ftn')) {
$ao = Address::findFTN($this->argument('ftn'));
if (! $ao) {
$this->error('FTN not found: ' .$this->argument('ftn'));
return self::FAILURE;
}
$this->info('our address:'.our_address($ao)->ftn);
return self::SUCCESS;
}
$this->table(['System','Node','Ours'],
our_nodes($ao ? $ao->domain : NULL)
->sortBy(fn($item)=>$this->option('node')
? sprintf('%s:%s',$item->system->name,$item->domain->name)
: sprintf('%s',$item->domain->name))
->map(fn($item)=>
[
'System'=>$item->system->name,
'Node'=>$item->ftn.' '.($item->echoareas->count() ? '^' : '').($item->fileareas->count() ? '*' : ''),
'Ours'=>our_address($item)?->ftn,
]));
return self::SUCCESS;
}
}

View File

@ -25,10 +25,11 @@ class ZoneCheck extends Command
$this->warn('Zone: '.$zo->zone_id);
$this->info(sprintf('- Our address(es): %s',our_address($do)->pluck('ftn4d')->join(',')));
$this->table(['id','ftn','role','parent','children','downlinks','uplink','send from','region_id','system','notes'],
$this->table(['id','region_id','ftn','role','parent','children','downlinks','uplink','send from','system','notes'],
$zo->addresses()->FTN()->active()->with(['system','nodes_hub'])->get()->transform(function($item) {
return [
'id'=>$item->id,
'region_id'=>$item->region_id,
'ftn'=>$item->ftn4d,
'role'=>$item->role_name,
'parent'=>$item->parent()?->ftn4d,
@ -36,7 +37,6 @@ class ZoneCheck extends Command
'downlinks'=>$item->downlinks()->count(),
'uplink'=>($x=$item->uplink())?->ftn4d,
'send from'=>$x ? our_address($item->uplink())?->ftn4d : '',
'region_id'=>$item->region_id,
'system'=>$item->system->name,
'notes'=>$item->isRoleOverride() ? 'Role Override' : '',
];

View File

@ -98,7 +98,10 @@ class SystemController extends Controller
$oo = Address::findOrNew($request->validated('submit'));
$oo->zone_id = $request->validated('zone_id');
$oo->security = $request->validated('security');
$oo->active = TRUE;
// Only change to active if it is new
if (! $oo->exists)
$oo->active = TRUE;
switch ($request->validated('action')) {
case 'region':

View File

@ -764,7 +764,7 @@ class Address extends Model
public function getFTNAttribute(): string
{
if (! $this->relationLoaded('zone'))
$this->load(['zone:id,domain_id,zone_id','zone.domain:domains.id,name']);
$this->load(['zone:id,domain_id,active,zone_id','zone.domain:domains.id,name,active']);
return sprintf('%s@%s',$this->getFTN4DAttribute(),$this->zone->domain->name);
}

View File

@ -84,14 +84,27 @@ if (! function_exists('hexstr')) {
/**
* Return our addresses.
*
* We have two address types:
* + a) address that we advertise to receive mail and use to package up mail (Public)
* + b) address that we accept and process mail
*
* a is a subset of b, where b might have addresses we used in the past but no longer (but mail still comes in, and we
* dont want to send out mail with those addresses anymore)
*
* Public addresses are when validated is set to true
* When determining our public addresses for a specific Address (when Address::class is passed), we only return addresses
* when security is not null
*
* If domain provided, limit the list to those within the domain - returning a Collection::class
* If address provided, return our address that would be used for the provided address - return Address::class
*
* @param Domain|Address|null $o - Domain or Address
* @param Domain|Address|null $o Domain or Address
* @param bool $public Return only public addresses
* @return Collection|Address|NULL
* @throws Exception
*/
function our_address(Domain|Address $o=NULL): Collection|Address|NULL
function our_address(Domain|Address $o=NULL,bool $public=TRUE): Collection|Address|NULL
{
if (! Config::has('setup'))
Config::set('setup',Setup::findOrFail(config('app.id')));
@ -99,7 +112,7 @@ function our_address(Domain|Address $o=NULL): Collection|Address|NULL
$so = Config::get('setup');
$so->loadMissing([
'system:id,name,sysop,location',
'system.akas:addresses.id,addresses.zone_id,region_id,host_id,node_id,point_id,addresses.system_id,addresses.active,role',
'system.akas:addresses.id,addresses.zone_id,region_id,host_id,node_id,point_id,addresses.system_id,addresses.active,role,validated,security',
'system.akas.zone:id,domain_id,zone_id',
'system.akas.zone.domain:id,name',
]);
@ -117,20 +130,22 @@ function our_address(Domain|Address $o=NULL): Collection|Address|NULL
// Looking for addresses in the same domain, and if fido.strict, addresses that have a higher role (ie: uplink)
case Address::class:
$filter = $so->system->akas
->filter(fn($item)=>$item->zone->domain_id === $o->zone->domain_id)
->filter(fn($item)=>((! $public) || ($public && $item->validated)) && ($item->zone->domain_id === $o->zone->domain_id))
->sortBy('role_id');
// If we are looking for a specific address, and there is only 1 result, return it, otherwise return what we have
if (config('fido.strict') && ($x=$filter->filter(fn($item)=>$item->role_id <= $o->role_id)->sortBy('role_id'))->count())
$filter = $x;
return $filter->count() ? $filter->last()->unsetRelation('nodes_hub') : NULL;
return $filter->count()
? ($filter->filter(fn($item)=>$item->region_id === $o->region_id)->count()
? $filter->last()
: $filter->first())->unsetRelation('nodes_hub')
: NULL;
// Addresses in this domain
case Domain::class:
return $so->system->akas
->filter(fn($item)=>$item->zone->domain_id === $o->id)
->sortBy('role_id');
->filter(fn($item)=>((! $public) || ($public && $item->validated)) && ($item->zone->domain_id === $o->id));
// We shouldnt get here
default:

View File

@ -112,21 +112,37 @@
@if($o->addresses->count())
<p>This system has the following addresses assigned to it:</p>
<table class="table monotable">
<table class="table monotable w-100" id="address_table">
<thead>
<tr>
<th>Address</th>
<th>Active</th>
<th>@if($o->setup)Parent @else Uplink @endif</th>
<th>Security</th>
<th colspan="2">Role</th>
<th>Role</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach ($o->addresses as $oo)
<tr>
<td @class(['trashed'=>$oo->trashed(),'inactive'=>(! $oo->trashed()) && (! $oo->active)])>{{ $oo->ftn }}<span class="float-end"><data value="{{ $oo->id }}:{{ $oo->validated ? 1 : 0 }}" class="validated"><i title="@if($oo->validated)Mail flowing @else Mail held @endif" @class(['bi','bi-activity'=>$oo->validated,'bi-radioactive'=>(! $oo->validated)])></i></data></span></td>
<td>{{ $oo->active ? 'YES' : 'NO' }}</td>
<tr @class(['text-secondary'=>$oo->trashed() || (! $oo->active_domain),'inactive'=>(! $oo->trashed()) && (! $oo->active)])>
<td>{{ $oo->ftn }}<span class="float-end"><data value="{{ $oo->id }}:{{ $oo->validated ? 1 : 0 }}" class="validated"><i title="@if($oo->validated)Mail flowing @else Mail held @endif" @class(['bi','bi-activity'=>$oo->validated,'bi-radioactive'=>(! $oo->validated)])></i></data></span></td>
<td>-{{ $oo->active ? 'Active' : 'Not Active' }}-</td>
<td>
@if($o->setup)
{{ ($oo->validated && $x=$oo->parent()) ? $x->ftn : '' }}
@else
@if($x=our_address($oo))
<!-- @todo To implement, if we enable address overriding -->
@if(true)
Auto <small class="text-secondary">[{{ $x->ftn4d }}]</small>
@else
<small>[Override]</small>
@endif
@endif
@endif
</td>
<td class="text-end">{{ $oo->security }}</td>
<td>{{ $oo->role_name }}</td>
<td class="nowrap actions">
@ -614,13 +630,16 @@
@endsection
@section('page-css')
@css('datatables')
<style>
span.btn.btn-danger a {
color: white
}
</style>
@endsection
@section('page-scripts')
@js('datatables')
<script type="text/javascript">
$(document).ready(function () {
if (window.location.hash) {
@ -664,6 +683,31 @@
@endcan
@endif
$('#address_table').DataTable({
paging: true,
pageLength: 25,
searching: true,
ordering: true,
order: [[1,'asc']],
conditionalPaging: {
style: 'fade',
speed: 500 // optional
},
rowGroup: {
dataSrc: [1],
},
columnDefs: [
{
targets: [1],
visible: false,
},
{
targets: [5],
orderable: false
}
],
});
$('data.validated').on('click',function(item) {
that = $(this);
var values = item.delegateTarget.value.split(':');