Compare commits
2 Commits
a601200df8
...
c49daadc5f
Author | SHA1 | Date | |
---|---|---|---|
c49daadc5f | |||
b59317871a |
64
app/Console/Commands/Debug/AddressCheckNode.php
Normal file
64
app/Console/Commands/Debug/AddressCheckNode.php
Normal 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;
|
||||
}
|
||||
}
|
@ -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' : '',
|
||||
];
|
||||
|
@ -98,6 +98,9 @@ class SystemController extends Controller
|
||||
$oo = Address::findOrNew($request->validated('submit'));
|
||||
$oo->zone_id = $request->validated('zone_id');
|
||||
$oo->security = $request->validated('security');
|
||||
|
||||
// Only change to active if it is new
|
||||
if (! $oo->exists)
|
||||
$oo->active = TRUE;
|
||||
|
||||
switch ($request->validated('action')) {
|
||||
|
@ -194,7 +194,7 @@ class AddressIdle implements ShouldQueue
|
||||
return collect();
|
||||
|
||||
$age = Carbon::now()->subDays($days)->endOfDay();
|
||||
$ours = our_address($do)->pluck('ftn');
|
||||
$ours = our_address($do,FALSE)->pluck('ftn');
|
||||
|
||||
return Address::FTN()
|
||||
->ActiveFTN()
|
||||
|
@ -60,7 +60,7 @@ class MessageProcess implements ShouldQueue
|
||||
$this->mo = unserialize(utf8_decode($this->mo));
|
||||
|
||||
// Load our details
|
||||
$ftns = our_address();
|
||||
$ftns = our_address(NULL,FALSE);
|
||||
|
||||
// If we are a netmail
|
||||
if ($this->mo instanceof Netmail) {
|
||||
|
@ -115,12 +115,12 @@ class NodelistImport implements ShouldQueue
|
||||
}
|
||||
|
||||
$file_crc = (int)$matches[4];
|
||||
$do = Domain::where('name',strtolower($matches[1] ?: $this->domain))->single();
|
||||
$do = Domain::where('name',strtolower($this->domain ?: $matches[1]))->single();
|
||||
|
||||
if (! $do) {
|
||||
Log::error(sprintf('%s:! Domain not found [%s].',static::LOGKEY,strtolower($matches[1] ?: $this->domain)));
|
||||
|
||||
throw new \Exception('Nodelist Domain not found: '.$this->file);
|
||||
throw new \Exception('Nodelist Domain not found: '.($this->domain ?: $matches[1]));
|
||||
}
|
||||
|
||||
$date = Carbon::createFromFormat('D, M d, Y H:i',$matches[2].'0:00');
|
||||
@ -143,6 +143,8 @@ class NodelistImport implements ShouldQueue
|
||||
elseif ($no->addresses->count()) {
|
||||
Log::error(sprintf('%s:! Nodelist [%s] for [%s] has existing records [%d]',self::LOGKEY,$date,$do->name,$no->addresses->count()));
|
||||
|
||||
// This can occur when a nodelist doesnt change, but is sent out anyway
|
||||
// @todo Need to immediately fail this job
|
||||
return;
|
||||
}
|
||||
|
||||
@ -291,7 +293,7 @@ class NodelistImport implements ShouldQueue
|
||||
Log::info(sprintf('%s:- Processing existing address [%s] (%d)',self::LOGKEY,$ao->ftn,$ao->id));
|
||||
|
||||
// If the address is linked to a user's system, or our system, we'll not process it any further
|
||||
if (our_address()->contains($ao->id)) {
|
||||
if (our_address(NULL,FALSE)->contains($ao->id)) {
|
||||
Log::info(sprintf('%s:! Limiting update to an address belonging to me',self::LOGKEY));
|
||||
$protect = TRUE;
|
||||
|
||||
@ -563,7 +565,7 @@ class NodelistImport implements ShouldQueue
|
||||
->filter(fn($item)=>(! $item->point_id))
|
||||
->pluck('id')
|
||||
->diff($no->addresses->pluck('id'))
|
||||
->diff(our_address($do)->pluck('id'))
|
||||
->diff(our_address($do,FALSE)->pluck('id'))
|
||||
->diff(our_nodes($do)->pluck('id'));
|
||||
|
||||
$remove = Address::whereIn('id',$remove)->get();
|
||||
|
@ -89,7 +89,7 @@ class PacketProcess implements ShouldQueue
|
||||
}
|
||||
|
||||
// Check the packet is to our address, if not we'll reject it.
|
||||
if (! our_address($pkt->tftn->zone->domain)->contains($pkt->tftn)) {
|
||||
if (! our_address($pkt->tftn->zone->domain,FALSE)->contains($pkt->tftn)) {
|
||||
Log::error(sprintf('%s:! Packet [%s] is not to our address? [%s]',self::LOGKEY,$this->filename,$pkt->tftn->ftn));
|
||||
|
||||
// @todo Notification::route('netmail',$pkt->fftn)->notify(new UnexpectedPacketToUs($this->filename));
|
||||
@ -123,7 +123,7 @@ class PacketProcess implements ShouldQueue
|
||||
Log::info(sprintf('%s:- Netmail from [%s] to [%s]',self::LOGKEY,$msg->fftn->ftn,$msg->tftn?->ftn ?: $msg->set_tftn));
|
||||
|
||||
// If we dont have a destination, we need to bounce it, if we would be the parent of the address
|
||||
if ((! $msg->tftn) && our_address()->contains(Address::newFTN($msg->set_tftn)?->parent())) {
|
||||
if ((! $msg->tftn) && our_address(NULL,FALSE)->contains(Address::newFTN($msg->set_tftn)?->parent())) {
|
||||
Log::alert(sprintf('%s:! Netmail destination [%s] doesnt exist, bouncing back to [%s]',self::LOGKEY,$msg->set_tftn,$pkt->fftn->ftn));
|
||||
|
||||
Notification::route('netmail',$msg->fftn)->notify(new NetmailNoDestination($msg));
|
||||
|
@ -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);
|
||||
}
|
||||
@ -1024,7 +1024,7 @@ class Address extends Model
|
||||
public function downlinks(): Collection
|
||||
{
|
||||
// We have no session data for this address, (and its not our address), by definition it has no children
|
||||
if (! $this->is_hosted && (! our_address()->pluck('id')->contains($this->id)))
|
||||
if (! $this->is_hosted && (! our_address(NULL,FALSE)->pluck('id')->contains($this->id)))
|
||||
return new Collection;
|
||||
|
||||
// If this system is not marked to default route for this address
|
||||
|
@ -184,12 +184,14 @@ final class Echomail extends Model implements Packet
|
||||
Log::debug(sprintf('%s:^ Message [%d] from point address is [%d]',self::LOGKEY,$model->id,$model->fftn->point_id));
|
||||
|
||||
// Make sure our sender is first in the path
|
||||
// @todo we need to capture the path for mail directly from points so we dont re-export to it.
|
||||
if (($model->fftn->point_id === 0) && (! $model->isFlagSet(Message::FLAG_LOCAL)) && (! $path->contains($model->fftn_id))) {
|
||||
Log::alert(sprintf('%s:? Echomail adding sender to start of PATH [%s].',self::LOGKEY,$model->fftn_id));
|
||||
$path->prepend($model->fftn_id);
|
||||
}
|
||||
|
||||
// Make sure our pktsrc is last in the path
|
||||
// @todo mail directly from points may have a blank path, so we need to make one up.
|
||||
if ($model->set->has('set_sender') && (! $path->contains($model->set->get('set_sender')->id)) && ($model->set->get('set_sender')->point_id === 0)) {
|
||||
Log::alert(sprintf('%s:? Echomail adding pktsrc to end of PATH [%s].',self::LOGKEY,$model->set->get('set_sender')->ftn));
|
||||
$path->push($model->set->get('set_sender')->id);
|
||||
@ -257,7 +259,7 @@ final class Echomail extends Model implements Packet
|
||||
->addresses
|
||||
->filter(function($item) use ($model) { return $model->echoarea->can_read($item->security); })
|
||||
->pluck('id')
|
||||
->diff(our_address($model->fftn->zone->domain)->pluck('id'))
|
||||
->diff(our_address($model->fftn->zone->domain,FALSE)->pluck('id'))
|
||||
->diff($seenby);
|
||||
|
||||
if ($exportto->count()) {
|
||||
|
@ -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:
|
||||
@ -140,7 +155,7 @@ function our_address(Domain|Address $o=NULL): Collection|Address|NULL
|
||||
|
||||
function our_hostname(Address $o): string
|
||||
{
|
||||
$our = our_address($o->domain)->first();
|
||||
$our = our_address($o->domain,FALSE)->first();
|
||||
$ourhostname = $our->system->address;
|
||||
|
||||
switch ($our->role_id) {
|
||||
|
@ -24,7 +24,7 @@ $user->load(['systems.akas.zone.domain.echoareas','systems.akas.echoareas']);
|
||||
<div class="col-12">
|
||||
@if(($x=$user
|
||||
->addresses()
|
||||
->diff(our_address())
|
||||
->diff(our_address(NULL,FALSE))
|
||||
->filter(fn($item)=>($item->point_id === 0) && ($item->zone->domain->isManaged())))->count())
|
||||
<h2>Hub Details for your nets</h2>
|
||||
|
||||
|
@ -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(':');
|
||||
|
Loading…
x
Reference in New Issue
Block a user