Consistency and SQL Query optimisations - focused around the UI

This commit is contained in:
2024-11-04 09:05:27 +11:00
parent f03533b62a
commit 3aeeed1686
21 changed files with 362 additions and 332 deletions

View File

@@ -1290,7 +1290,7 @@ final class Binkp extends BaseProtocol
Log::info(sprintf('%s:- SECURE',self::LOGKEY));
// @todo Since we have connected, if the node was marked down/hold reset that
// Notification::route('netmail',$ao->system->uncommon()->first()->withoutRelations())->notify(new NodeMarkedDownNetmail($ao->withoutRelations()));
// Notification::route('netmail',$ao->system->aka_unknown()->first()->withoutRelations())->notify(new NodeMarkedDownNetmail($ao->withoutRelations()));
}
return $this->binkp_hsdone();
@@ -1389,7 +1389,7 @@ final class Binkp extends BaseProtocol
$this->msgs(self::BPM_OK,sprintf('%ssecure',$have_pwd ? '' : 'non-'));
// @todo Since we have connected, if the node was marked down/hold reset that
// Notification::route('netmail',$ao->system->uncommon()->first()->withoutRelations())->notify(new NodeMarkedDownNetmail($ao->withoutRelations()));
// Notification::route('netmail',$ao->system->aka_unknown()->first()->withoutRelations())->notify(new NodeMarkedDownNetmail($ao->withoutRelations()));
} else {
$this->msgs(self::OK,'non-secure');

View File

@@ -1062,7 +1062,7 @@ final class EMSI extends BaseProtocol implements CRCInterface,ZmodemInterface
}
// @todo Since we have connected, if the node was marked down/hold reset that
// Notification::route('netmail',$ao->system->uncommon()->first()->withoutRelations())->notify(new NodeMarkedDownNetmail($ao->withoutRelations()));
// Notification::route('netmail',$ao->system->aka_unknown()->first()->withoutRelations())->notify(new NodeMarkedDownNetmail($ao->withoutRelations()));
// @todo Lock Node AKAs

View File

@@ -115,7 +115,7 @@ class DomainController extends Controller
if (! $o->public && ! Gate::check('admin',$o))
abort(404);
$o->load(['zones.system','zones.domain','zones.addresses.nodes_hub','zones.addresses']);
$o->load(['zones.system','zones.domain','zones.addresses.nodes_hub','zones.addresses.echomail_from']);
return view('domain.view')
->with('o',$o);

View File

@@ -66,7 +66,17 @@ class SystemController extends Controller
->with('saved',TRUE);
}
$o->load(['addresses.zone.domain','addresses.system','sessions.domain','sessions.systems']);
$o->loadMissing([
'zcs',
// For 'ftn' to work
'addresses.zone:id,zone_id,domain_id,active',
'addresses.zone.domain:id,name,active',
// For 'role'
'addresses.system:id,address',
// For system addedit
'sessions.domain:id,name,active',
'sessions.systems:id',
]);
return view('system.addedit')
->with('action',$o->exists ? 'update_nn' : 'create')
@@ -611,31 +621,12 @@ class SystemController extends Controller
*/
public function register(SystemRegisterRequest $request)
{
// Step 1, show the user a form to select an existing defined system
if ($request->isMethod('GET'))
return view('user.system.register');
if ($request->action === 'register' && $request->name && is_numeric($request->name))
return view('user.system.widget.register_confirm')
->with('o',System::findOrFail($request->name));
$o = System::findOrNew(is_numeric($request->system_id) ? $request->system_id : NULL);
// If the system exists, and we are 'register', we'll start the address claim process
if ($o->exists && $request->action === 'Link') {
$validate = Setup::findOrFail(config('app.id'))->system->inMyZones($o->addresses);
// If we have addresses, we'll trigger the routed netmail
if ($validate->count()) {
Notification::route('netmail',$x=$validate->first())->notify(new AddressLink(Auth::user()));
AddressPoll::dispatch($x)->delay(15);
}
return view('user.system.widget.register_send')
->with('validate',$validate)
->with('o',$o);
}
// If the system doesnt exist, we'll create it
if (! $o->exist) {
$o->sysop = Auth::user()->name;

View File

@@ -104,8 +104,8 @@ class AddressIdle implements ShouldQueue
}
// Netmail Alert (to othernet network address)
if ($ao->system->uncommon()->count()) {
Notification::route('netmail',$ao->system->uncommon()->first()->withoutRelations())->notify(new NodeDelistedNetmail($ao->withoutRelations()));
if ($ao->system->aka_unknown()->count()) {
Notification::route('netmail',$ao->system->aka_unknown()->first()->withoutRelations())->notify(new NodeDelistedNetmail($ao->withoutRelations()));
$contact = TRUE;
}
@@ -140,8 +140,8 @@ class AddressIdle implements ShouldQueue
}
// Netmail Alert (to othernet network address)
if ($ao->system->uncommon()->count()) {
Notification::route('netmail',$ao->system->uncommon()->first()->withoutRelations())->notify(new NodeMarkedDownNetmail($ao->withoutRelations()));
if ($ao->system->aka_unknown()->count()) {
Notification::route('netmail',$ao->system->aka_unknown()->first()->withoutRelations())->notify(new NodeMarkedDownNetmail($ao->withoutRelations()));
$contact = TRUE;
}
@@ -188,8 +188,8 @@ class AddressIdle implements ShouldQueue
}
// Netmail Alert (to othernet network address)
if ($ao->system->uncommon()->count()) {
Notification::route('netmail',$ao->system->uncommon()->first()->withoutRelations())->notify(new NodeMarkedHoldNetmail($ao->withoutRelations()));
if ($ao->system->aka_unknown()->count()) {
Notification::route('netmail',$ao->system->aka_unknown()->first()->withoutRelations())->notify(new NodeMarkedHoldNetmail($ao->withoutRelations()));
$contact = TRUE;
}
@@ -214,21 +214,9 @@ class AddressIdle implements ShouldQueue
$age = Carbon::now()->subDays($days)->endOfDay();
return Address::select([
'addresses.id',
'system_id',
'zone_id',
'region_id',
'host_id',
'node_id',
'point_id',
'addresses.active',
'hub_id',
'role',
'addresses.updated_at',
])
->activeFTN()
->where('systems.active',TRUE)
return Address::FTN()
->ActiveFTN()
->addSelect(['addresses.updated_at'])
->where(fn($query)=>$query->where('point_id',0)->orWhereNull('point_id'))
->whereIn('addresses.id',our_nodes($do)->pluck('id'))
->when($ao,fn($query)=>$query->where('addresses.id',$ao->id))
@@ -236,9 +224,7 @@ class AddressIdle implements ShouldQueue
->whereRaw(sprintf('((role IS NULL) OR (role=0) OR ((role & %d) > 0))',$flags))
->whereRaw(sprintf('((role IS NULL) OR ((role & %d) = 0))',Address::NODE_KEEP))
->join('systems',['systems.id'=>'addresses.system_id'])
->ftnOrder()
->with(['system','zone.domain'])
->dontCache()
//->with(['system','zone.domain'])
->get();
}
}

View File

@@ -395,16 +395,14 @@ class Address extends Model
*
* @param $query
* @return mixed
* @note zones and domains needs to be joined in the base call, or use FTN()
*/
public function scopeActiveFTN($query)
{
return $query->select($this->getTable().'.*')
->join('zones',['zones.id'=>'addresses.zone_id'])
->join('domains',['domains.id'=>'zones.domain_id'])
return $query
->where('zones.active',TRUE)
->where('domains.active',TRUE)
->active()
->FTNorder();
->active();
}
/**
@@ -416,13 +414,21 @@ class Address extends Model
public function scopeFTN($query)
{
return $query
->select(['id','addresses.zone_id','host_id','node_id','point_id','system_id'])
->select(['addresses.id','region_id','host_id','node_id','point_id','addresses.zone_id','addresses.active','role','security','addresses.system_id','addresses.active','validated'])
->join('zones',['zones.id'=>'addresses.zone_id'])
->join('domains',['domains.id'=>'zones.domain_id'])
->orderBy('domains.name')
->orderBy('region_id')
->orderBy('host_id')
->orderBy('node_id')
->orderBy('point_id')
->with([
'zone:zones.id,domain_id,zone_id',
'zone.domain:domains.id,name',
'zone:zones.id,domain_id,zone_id,active',
'zone.domain:domains.id,name,active,public',
]);
}
/** @deprecated use FTN() */
public function scopeFTNOrder($query)
{
return $query

View File

@@ -48,35 +48,39 @@ class System extends Model
$uo = Auth::user();
return $query
->when($uo && ! $uo->isAdmin(),function($query) use ($uo) {
return $query->whereIn('id',$uo->systems->pluck('id'))
->orWhere($this->getTable().'.active',TRUE);
},function($query) { $query->where($this->getTable().'.active',TRUE); })
->when(
$uo && ! $uo->isAdmin(),
fn($query)=>
$query
->whereIn('id',$uo->systems->pluck('id'))
->orWhere($this->getTable().'.active',TRUE),
fn($query)=>$query->where($this->getTable().'.active',TRUE))
->orderBy('name');
}
/* RELATIONS */
/**
* All addresses assigned to a system, including addresses pending deletion
* @return mixed
*/
public function addresses()
{
return $this->hasMany(Address::class)
->withTrashed()
->FTNorder();
->FTN()
->withTrashed();
}
/**
* System addresses that are active
*
* @return mixed
*/
public function akas()
{
return $this->hasMany(Address::class)
->select('addresses.*')
->join('zones',['zones.id'=>'addresses.zone_id'])
->join('domains',['domains.id'=>'zones.domain_id'])
->where('addresses.active',TRUE)
->where('zones.active',TRUE)
->where('domains.active',TRUE)
->orderBy('domains.name')
->with(['zone.domain'])
->FTNorder()
->orderBy('role','ASC');
->FTN()
->ActiveFTN();
}
public function mailers()
@@ -136,7 +140,14 @@ class System extends Model
*/
public function zcs()
{
return $this->hasMany(Zone::class);
return $this->hasMany(Zone::class)
->select(['zones.id','zone_id','domain_id','system_id','zones.active'])
->join('domains',['domains.id'=>'zones.domain_id'])
->orderBy('domains.name')
->orderBy('zone_id')
->with([
'domain:id,name,active',
]);
}
/**
@@ -189,6 +200,58 @@ class System extends Model
/* METHODS */
/**
* Return the ACTIVE addresses that are common with our addresses
*
* @return Collection
* @throws \Exception
*/
public function aka_common(): Collection
{
$our = our_address()->pluck('zone.domain_id')->unique();
// Return our akas, filter with our_addresses()
return $this->akas->filter(fn($item)=>$our->contains($item->zone->domain_id));
}
/**
* Return the ACTIVE addresses that we auth with
*
* @return Collection
* @throws \Exception
*/
public function aka_known(): Collection
{
return $this->aka_common()
->filter(fn($item)=>$this->sessions->contains($item->zone_id));
}
/**
* Return the ACTIVE addresses in the same networks as us, but dont auth here
*
* @return Collection
* @throws \Exception
*/
public function aka_unknown(): Collection
{
return $this->aka_common()
->filter(fn($item)=>! $this->sessions->contains($item->zone_id));
}
/**
* Return the AKAs that are in networks not common with us
*
* @return Collection
* @throws \Exception
*/
public function aka_uncommon(): Collection
{
$our = our_address()->pluck('zone.domain_id')->unique();
// Return our akas, filter with our_addresses()
return $this->akas->filter(fn($item)=>! $our->contains($item->zone->domain_id));
}
public function echoareas()
{
return Echoarea::select('echoareas.*')
@@ -250,28 +313,13 @@ class System extends Model
: $akas;
}
/**
* Parse the addresses and return which ones are in my zones
*
* @param \Illuminate\Database\Eloquent\Collection $addresses
* @param int $type
* @return Collection
*/
public function inMyZones(Collection $addresses,int $type=(Address::NODE_HC|Address::NODE_NN|Address::NODE_POINT)): Collection
{
$myzones = $this->addresses->pluck('zone_id')->unique();
return $addresses->filter(function($item) use ($myzones,$type) {
return ($item->role & $type) && ($myzones->search($item->zone_id) !== FALSE);
});
}
/**
* Return the packet that this system uses
*
* @param Address $ao
* @param string|null $password
* @return Packet
* @throws \Exception
*/
public function packet(Address $ao,string $password=NULL): Packet
{
@@ -289,22 +337,7 @@ class System extends Model
{
return Job::where('queue',AddressPoll::QUEUE)
->get()
->where(function($item) {
return $this->akas->pluck('id')->search($item->command->address->id) !== FALSE; })
->where(fn($item)=>$this->akas->pluck('id')->contains($item->command->address->id))
->last();
}
/**
* Return other addresses that are not collected here, but are on the same network as us.
*
* @return \Illuminate\Database\Eloquent\Collection
* @throws \Exception
*/
public function uncommon(): Collection
{
$our = our_address();
return $this->akas
->filter(fn($item)=>(($x=$item->parent()) && (! $our->contains($x)) && ($our->pluck('zone.domain_id')->contains($item->zone->domain_id))));
}
}

View File

@@ -75,19 +75,14 @@ class User extends Authenticatable implements MustVerifyEmail
/* GENERAL METHODS */
public function addresses(Domain $o=NULL): Collection
public function addresses(): Collection
{
return Address::select('addresses.*')
->join('systems',['systems.id'=>'addresses.system_id'])
->join('system_user',['system_user.system_id'=>'systems.id'])
->when(! is_null($o),function($query) use ($o) {
return $query
->join('zones',['zones.id'=>'addresses.zone_id'])
->where('zones.domain_id',$o->id);
})
->where('system_user.user_id',$this->id)
->activeFTN()
->with(['zone.domain'])
->ActiveFTN()
->FTN()
->get();
}

View File

@@ -46,9 +46,9 @@ class NodeMarkedDown extends Netmails //implements ShouldQueue
->addText(sprintf("Your system has been marked **DOWN**, because it hasnt polled **%s** with address %s since **%s** (%d days).\r",$this->ao->zone->domain->name,$this->ao->ftn4d,$this->ao->system->last_seen?->format('Y-m-d') ?: 'Not seen',$this->ao->system->last_seen?->diffInDays($now)))
->addText("\r")
->addText("You have (waiting for collection):\r")
->addText(sprintf('* %s Netmails',number_format($this->ao->netmailWaiting()->count())))
->addText(sprintf('* %s Echomails',number_format($this->ao->echomailWaiting()->count())))
->addText(sprintf('* %s Files',number_format($this->ao->filesWaiting()->count())))
->addText(sprintf("* %s Netmails\r",number_format($this->ao->netmailWaiting()->count())))
->addText(sprintf("* %s Echomails\r",number_format($this->ao->echomailWaiting()->count())))
->addText(sprintf("* %s Files\r",number_format($this->ao->filesWaiting()->count())))
->addText("\r")
->addText(sprintf("Your system will automatically be **DE-LISTED** if your system hasnt polled to collected your mail/file(s) by **%s**\r\r",$now->addDays(7)->format('Y-m-d')))
->addText("If you think you've received this netmail by mistake or need help, please let me know.\r");

View File

@@ -47,9 +47,9 @@ class NodeMarkedHold extends Netmails //implements ShouldQueue
->addText(sprintf("Your system has been marked **HOLD**, because it hasnt polled **%s** with address %s since **%s** (%d days).\r",$this->ao->zone->domain->name,$this->ao->ftn4d,$this->ao->system->last_seen?->format('Y-m-d') ?: 'Not seen',$this->ao->system->last_seen?->diffInDays($now)))
->addText("\r")
->addText("You have (waiting for collection):\r")
->addText(sprintf('* %s Netmails',number_format($this->ao->netmailWaiting()->count())))
->addText(sprintf('* %s Echomails',number_format($this->ao->echomailWaiting()->count())))
->addText(sprintf('* %s Files',number_format($this->ao->filesWaiting()->count())))
->addText(sprintf("* %s Netmails\r",number_format($this->ao->netmailWaiting()->count())))
->addText(sprintf("* %s Echomails\r",number_format($this->ao->echomailWaiting()->count())))
->addText(sprintf("* %s Files\r",number_format($this->ao->filesWaiting()->count())))
->addText("\r")
->addText(sprintf("To clear this status, all you need to do make sure your system polls and collects mail by **%s**\r\r",($this->ao->system->last_seen ?: Carbon::now())->addDays(config('fido.idle.down'))->format('Y-m-d')))
->addText("If you think you've received this netmail by mistake or need help, please let me know.\r");

View File

@@ -114,6 +114,7 @@ function our_address(Domain|Address $o=NULL): Collection|Address|NULL
// We are requesting a list of addresses for a Domain, or a specific Address, and we have more than 1
switch (get_class($o)) {
// 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)
@@ -125,6 +126,7 @@ function our_address(Domain|Address $o=NULL): Collection|Address|NULL
return $filter->count() ? $filter->last()->unsetRelation('nodes_hub') : NULL;
// Addresses in this domain
case Domain::class:
return $so->system->akas
->filter(fn($item)=>$item->zone->domain_id === $o->id)