Mail routing parent/children, domain name validation, nodelist import changes and other fixes
This commit is contained in:
@@ -317,7 +317,7 @@ class Packet extends FTNBase
|
||||
private function newHeader(Address $o): void
|
||||
{
|
||||
$date = Carbon::now();
|
||||
$ao = Setup::findOrFail(config('app.id'))->system->match($o);
|
||||
$ao = Setup::findOrFail(config('app.id'))->system->match($o->zone);
|
||||
|
||||
// Create Header
|
||||
$this->header = [
|
||||
|
@@ -14,9 +14,10 @@ class DomainController extends Controller
|
||||
public const NODE_RC = 1<<1; // Region
|
||||
public const NODE_NC = 1<<2; // Host
|
||||
public const NODE_HC = 1<<3; // Hub
|
||||
public const NODE_PVT = 1<<4; // Pvt
|
||||
public const NODE_HOLD = 1<<5; // Hold
|
||||
public const NODE_DOWN = 1<<6; // Down
|
||||
public const NODE_POINT = 1<<4; // Point
|
||||
public const NODE_PVT = 1<<5; // Pvt
|
||||
public const NODE_HOLD = 1<<6; // Hold
|
||||
public const NODE_DOWN = 1<<7; // Down
|
||||
|
||||
// http://ftsc.org/docs/frl-1002.001
|
||||
public const NUMBER_MAX = 0x7fff;
|
||||
@@ -27,7 +28,7 @@ class DomainController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* Add or edit a node
|
||||
* Add or edit a domain
|
||||
*/
|
||||
public function add_edit(Request $request,Domain $o)
|
||||
{
|
||||
@@ -35,7 +36,8 @@ class DomainController extends Controller
|
||||
$this->authorize('admin',$o);
|
||||
|
||||
$request->validate([
|
||||
'name' => 'required|max:8|unique:domains,name,'.($o->exists ? $o->id : 0),
|
||||
// http://ftsc.org/docs/old/fsp-1028.002
|
||||
'name' => 'required|max:8|regex:/^[a-z-_~]{1,8}$/|unique:domains,name,'.($o->exists ? $o->id : 0),
|
||||
'dnsdomain' => 'nullable|regex:/^(?!:\/\/)(?=.{1,255}$)((.{1,63}\.){1,127}(?![0-9]*$)[a-z0-9-]+\.?)$/i|unique:domains,dnsdomain,'.($o->exists ? $o->id : NULL),
|
||||
'active' => 'required|boolean',
|
||||
'public' => 'required|boolean',
|
||||
|
@@ -121,6 +121,32 @@ class SystemController extends Controller
|
||||
]
|
||||
]);
|
||||
|
||||
// Find the Hub address
|
||||
// Find the zones <HOST>/0 address, and assign it to this host.
|
||||
$oo = Address::where('zone_id',$request->zone_id)
|
||||
->where('region_id',$request->region_id)
|
||||
->where('host_id',$request->host_id_new)
|
||||
->where('node_id',0)
|
||||
->where('point_id',0)
|
||||
->single();
|
||||
|
||||
// Its not defined, so we'll create it.
|
||||
if (! $oo) {
|
||||
$oo = new Address;
|
||||
$oo->forceFill([
|
||||
'zone_id'=>$request->zone_id,
|
||||
'region_id'=>$request->region_id,
|
||||
'host_id'=>$request->host_id_new,
|
||||
'node_id'=>0,
|
||||
'point_id'=>0,
|
||||
'role'=>DomainController::NODE_NC,
|
||||
]);
|
||||
}
|
||||
|
||||
$oo->system_id = $request->system_id;
|
||||
$oo->active = TRUE;
|
||||
$o->addresses()->save($oo);
|
||||
|
||||
$oo = new Address;
|
||||
$oo->zone_id = $request->post('zone_id');
|
||||
$oo->region_id = $request->post('region_id');
|
||||
@@ -200,8 +226,8 @@ class SystemController extends Controller
|
||||
$validate = $request->validate([
|
||||
'zone_id' => 'required|exists:zones,id',
|
||||
'sespass' => 'required|string|min:4',
|
||||
'pktpass' => 'required|string|min:4|max:8',
|
||||
'ticpass' => 'required|string|min:4',
|
||||
'pktpass' => 'nullable|string|min:4|max:8',
|
||||
'ticpass' => 'nullable|string|min:4',
|
||||
'fixpass' => 'required|string|min:4',
|
||||
]);
|
||||
|
||||
@@ -242,6 +268,8 @@ class SystemController extends Controller
|
||||
return redirect()->action([self::class,'home']);
|
||||
}
|
||||
|
||||
$o->load(['addresses.zone.domain']);
|
||||
|
||||
return view('system.addedit')
|
||||
->with('o',$o);
|
||||
}
|
||||
|
@@ -5,7 +5,7 @@ namespace App\Http\Controllers;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
use App\Models\Zone;
|
||||
use App\Models\{Address,Zone};
|
||||
|
||||
class ZoneController extends Controller
|
||||
{
|
||||
@@ -64,6 +64,30 @@ class ZoneController extends Controller
|
||||
|
||||
$o->save();
|
||||
|
||||
// Find the zones 0/0 address, and assign it to this host.
|
||||
$ao = Address::where('zone_id',$request->zone_id)
|
||||
->where('region_id',0)
|
||||
->where('host_id',0)
|
||||
->where('node_id',0)
|
||||
->where('point_id',0)
|
||||
->single();
|
||||
|
||||
// Its not defined, so we'll create it.
|
||||
if (! $ao) {
|
||||
$ao = new Address;
|
||||
$ao->forceFill([
|
||||
'region_id'=>0,
|
||||
'host_id'=>0,
|
||||
'node_id'=>0,
|
||||
'point_id'=>0,
|
||||
'role'=>DomainController::NODE_ZC,
|
||||
]);
|
||||
}
|
||||
|
||||
$ao->system_id = $request->system_id;
|
||||
$ao->active = TRUE;
|
||||
$o->addresses()->save($ao);
|
||||
|
||||
return redirect()->action([self::class,'home']);
|
||||
}
|
||||
|
||||
|
@@ -89,7 +89,6 @@ class NodelistImport implements ShouldQueue
|
||||
|
||||
switch ($fields[0]) {
|
||||
case 'Zone': $zone = $fields[1];
|
||||
// We ignore the Zone entries, since they are dynamically created.
|
||||
Zone::unguard();
|
||||
$zo = Zone::firstOrNew([
|
||||
'zone_id'=>$zone,
|
||||
@@ -99,7 +98,7 @@ class NodelistImport implements ShouldQueue
|
||||
Zone::reguard();
|
||||
|
||||
$region = 0;
|
||||
$host = $fields[1];
|
||||
$host = 0;
|
||||
$hub_id = NULL;
|
||||
$role = DomainController::NODE_ZC;
|
||||
|
||||
@@ -118,8 +117,7 @@ class NodelistImport implements ShouldQueue
|
||||
$hub_id = NULL;
|
||||
$role = DomainController::NODE_NC;
|
||||
|
||||
// We ignore the Host entries, since they are dynamically created.
|
||||
continue 2;
|
||||
break;
|
||||
|
||||
case 'Hub':
|
||||
$node = $fields[1];
|
||||
@@ -243,10 +241,10 @@ class NodelistImport implements ShouldQueue
|
||||
|
||||
try {
|
||||
$so->addresses()->save($ao);
|
||||
if ($role == DomainController::NODE_HC)
|
||||
if ($ao->role == DomainController::NODE_HC)
|
||||
$hub_id = $ao->id;
|
||||
|
||||
$this->no->addresses()->attach($ao,['role'=>$role]);
|
||||
$this->no->addresses()->attach($ao,['role'=>$ao->role]);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
Log::error(sprintf('%s:Error with line [%s] (%s)',self::LOGKEY,$line,$e->getMessage()),['fields'=>$fields]);
|
||||
|
@@ -30,37 +30,150 @@ class Address extends Model
|
||||
/* RELATIONS */
|
||||
|
||||
/**
|
||||
* Find children dependant on this record
|
||||
* Find children dependent on this record
|
||||
*/
|
||||
public function children()
|
||||
{
|
||||
switch (strtolower($this->role)) {
|
||||
case 'region':
|
||||
return $this->hasMany(self::class,'region_id','region_id')
|
||||
->where('zone_id',$this->zone_id)
|
||||
->where(function($q) {
|
||||
return $q->where('host_id',0)
|
||||
->orWhere('role',DomainController::NODE_NC);
|
||||
})
|
||||
->where('id','<>',$this->id);
|
||||
// We have no session data for this address, by definition it has no children
|
||||
if (! $this->session('sespass'))
|
||||
return $this->hasMany(self::class,'id','void');
|
||||
|
||||
case 'host':
|
||||
return $this->hasMany(self::class,'host_id','host_id')
|
||||
switch ($this->role) {
|
||||
case DomainController::NODE_ZC:
|
||||
$children = self::select('addresses.*')
|
||||
->where('zone_id',$this->zone_id);
|
||||
|
||||
break;
|
||||
|
||||
case DomainController::NODE_RC:
|
||||
$children = self::select('addresses.*')
|
||||
->where('zone_id',$this->zone_id)
|
||||
->where('region_id',$this->region_id);
|
||||
|
||||
break;
|
||||
|
||||
case DomainController::NODE_NC:
|
||||
$children = self::select('addresses.*')
|
||||
->where('zone_id',$this->zone_id)
|
||||
->where('region_id',$this->region_id)
|
||||
->whereNull('hub_id')
|
||||
->where('id','<>',$this->id);
|
||||
->where('host_id',$this->host_id);
|
||||
|
||||
case 'hub':
|
||||
return $this->hasMany(self::class,'hub_id','id');
|
||||
break;
|
||||
|
||||
case 'node':
|
||||
case DomainController::NODE_HC:
|
||||
// Identify our children.
|
||||
$children = self::select('addresses.*')
|
||||
->where('hub_id',$this->id);
|
||||
|
||||
break;
|
||||
|
||||
case DomainController::NODE_ACTIVE:
|
||||
case DomainController::NODE_POINT:
|
||||
// Nodes dont have children, but must return a relationship instance
|
||||
return $this->hasOne(self::class,NULL,'void');
|
||||
|
||||
default:
|
||||
throw new Exception('Unknown role: '.$this->role);
|
||||
throw new Exception('Unknown role: '.serialize($this->role));
|
||||
}
|
||||
|
||||
// Remove any children that we have session details for (SAME AS HC)
|
||||
$sessions = self::select('hubnodes.*')
|
||||
->join('system_zone',['system_zone.system_id'=>'addresses.system_id','system_zone.zone_id'=>'addresses.zone_id'])
|
||||
->join('addresses as hubnodes',['hubnodes.zone_id'=>'addresses.zone_id','hubnodes.id'=>'addresses.id'])
|
||||
->where('addresses.zone_id',$this->zone_id)
|
||||
->where('addresses.system_id','<>',$this->system_id)
|
||||
->whereIN('addresses.system_id',$children->get()->pluck('system_id'));
|
||||
|
||||
// For each of the session, identify their children
|
||||
$session_kids = collect();
|
||||
foreach ($sessions->get() as $so)
|
||||
$session_kids = $session_kids->merge(($x=$so->children) ? $x->pluck('id') : []);
|
||||
|
||||
// ZC's receive all mail, except for defined nodes, and defined hubs/hosts/rcs
|
||||
return $this->hasMany(self::class,'zone_id','zone_id')
|
||||
->whereIn('id',$children->get()->pluck('id')->toArray())
|
||||
->whereNotIn('id',$sessions->get()->pluck('id')->toArray())
|
||||
->whereNotIn('id',$session_kids->toArray())
|
||||
->where('system_id','<>',$this->system_id)
|
||||
->select('addresses.*')
|
||||
->orderBy('region_id')
|
||||
->orderBy('host_id')
|
||||
->orderBy('node_id')
|
||||
->orderBy('point_id')
|
||||
->with(['zone.domain']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Who we send this systems mail to.
|
||||
*
|
||||
* @return Address|null
|
||||
* @throws Exception
|
||||
*/
|
||||
public function parent(): ?Address
|
||||
{
|
||||
// If we are have session password, then we dont have a parent
|
||||
if ($this->session('sespass'))
|
||||
return $this;
|
||||
|
||||
switch ($this->role) {
|
||||
// ZCs dont have parents.
|
||||
case DomainController::NODE_ZC:
|
||||
return NULL;
|
||||
|
||||
// RC
|
||||
case DomainController::NODE_RC:
|
||||
$parent = self::where('zone_id',$this->zone_id)
|
||||
->where('region_id',0)
|
||||
->where('host_id',0)
|
||||
->where('node_id',0)
|
||||
->single();
|
||||
|
||||
break;
|
||||
|
||||
// Hosts
|
||||
case DomainController::NODE_NC:
|
||||
// See if we have a RC
|
||||
$parent = self::where('zone_id',$this->zone_id)
|
||||
->where('region_id',$this->region_id)
|
||||
->where('host_id',0)
|
||||
->where('node_id',0)
|
||||
->single();
|
||||
|
||||
if (! $parent) {
|
||||
// See if we have a RC
|
||||
$parent = self::where('zone_id',$this->zone_id)
|
||||
->where('region_id',0)
|
||||
->where('host_id',0)
|
||||
->where('node_id',0)
|
||||
->single();
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
// Hubs
|
||||
case DomainController::NODE_HC:
|
||||
// Normal Nodes
|
||||
case DomainController::NODE_ACTIVE:
|
||||
// If we are a child of a hub, then check our hub
|
||||
$parent = (($this->hub_id)
|
||||
? self::where('id',$this->hub_id)
|
||||
: self::where('zone_id',$this->zone_id)
|
||||
->where('region_id',$this->region_id)
|
||||
->where('host_id',$this->host_id)
|
||||
->where('node_id',0))
|
||||
->single();
|
||||
|
||||
break;
|
||||
|
||||
case DomainController::NODE_POINT:
|
||||
// @todo Points - if the boss is defined, we should return it.
|
||||
return NULL;
|
||||
|
||||
default:
|
||||
throw new Exception('Unknown role: '.serialize($this->role));
|
||||
}
|
||||
|
||||
return $parent?->parent();
|
||||
}
|
||||
|
||||
public function system()
|
||||
@@ -95,23 +208,21 @@ class Address extends Model
|
||||
return sprintf('%s.%d',$this->getFTN3DAttribute(),$this->point_id);
|
||||
}
|
||||
|
||||
public function getRoleAttribute($value)
|
||||
public function getRoleNameAttribute(): string
|
||||
{
|
||||
switch ($value) {
|
||||
case DomainController::NODE_ZC;
|
||||
return 'Zone';
|
||||
case DomainController::NODE_RC;
|
||||
return 'Region';
|
||||
case DomainController::NODE_NC;
|
||||
return 'Host';
|
||||
case DomainController::NODE_HC;
|
||||
return 'Hub';
|
||||
case DomainController::NODE_PVT;
|
||||
return 'PVT';
|
||||
case DomainController::NODE_DOWN;
|
||||
return 'DOWN';
|
||||
case NULL:
|
||||
return 'Node';
|
||||
switch ($this->role) {
|
||||
case DomainController::NODE_ACTIVE:
|
||||
return 'NODE';
|
||||
case DomainController::NODE_ZC:
|
||||
return 'ZC';
|
||||
case DomainController::NODE_RC:
|
||||
return 'RC';
|
||||
case DomainController::NODE_NC:
|
||||
return 'NC';
|
||||
case DomainController::NODE_HC:
|
||||
return 'HUB';
|
||||
case DomainController::NODE_POINT:
|
||||
return 'POINT';
|
||||
default:
|
||||
return '?';
|
||||
}
|
||||
@@ -130,17 +241,48 @@ class Address extends Model
|
||||
{
|
||||
$ftn = self::parseFTN($ftn);
|
||||
|
||||
// Are we looking for a region address
|
||||
if (($ftn['f'] === 0) && $ftn['p'] === 0) {
|
||||
$o = (new self)->active()
|
||||
->select('addresses.*')
|
||||
->where('zones.zone_id',$ftn['z'])
|
||||
->where(function($q) use ($ftn) {
|
||||
return $q
|
||||
->where(function($q) use ($ftn) {
|
||||
return $q->where('region_id',$ftn['n'])
|
||||
->where('host_id',0);
|
||||
});
|
||||
})
|
||||
->where('node_id',$ftn['f'])
|
||||
->where('point_id',$ftn['p'])
|
||||
->join('zones',['zones.id'=>'addresses.zone_id'])
|
||||
->join('domains',['domains.id'=>'zones.domain_id'])
|
||||
->where('zones.active',TRUE)
|
||||
->where('domains.active',TRUE)
|
||||
->where('addresses.active',TRUE)
|
||||
->when($ftn['d'],function($query,$domain) {
|
||||
$query->where('domains.name',$domain);
|
||||
})
|
||||
->when((! $ftn['d']),function($query) {
|
||||
$query->where('domains.default',TRUE);
|
||||
})
|
||||
->single();
|
||||
|
||||
if ($o && $o->system->active)
|
||||
return $o;
|
||||
}
|
||||
|
||||
$o = (new self)->active()
|
||||
->select('addresses.*')
|
||||
->where('zones.zone_id',$ftn['z'])
|
||||
->where('host_id',$ftn['n'])
|
||||
->where('node_id',$ftn['f'])
|
||||
->where('point_id',$ftn['p'])
|
||||
->join('zones',['zones.id'=>'addresses.zone_id'])
|
||||
->join('domains',['domains.id'=>'zones.domain_id'])
|
||||
->where('zones.active',TRUE)
|
||||
->where('domains.active',TRUE)
|
||||
->where('addresses.active',TRUE)
|
||||
->where('node_id',$ftn['f'])
|
||||
->where('point_id',$ftn['p'])
|
||||
->when($ftn['d'],function($query,$domain) {
|
||||
$query->where('domains.name',$domain);
|
||||
})
|
||||
|
@@ -7,6 +7,7 @@ use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
use App\Http\Controllers\DomainController;
|
||||
use App\Traits\ScopeActive;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
class System extends Model
|
||||
{
|
||||
@@ -61,12 +62,12 @@ class System extends Model
|
||||
/**
|
||||
* Return the system's address in the same zone
|
||||
*
|
||||
* @param Address $o
|
||||
* @return Address
|
||||
* @param Zone $o
|
||||
* @return Collection
|
||||
*/
|
||||
public function match(Address $o): Address
|
||||
public function match(Zone $o): Collection
|
||||
{
|
||||
return $this->addresses->where('zone_id',$o->zone_id)->first();
|
||||
return $this->addresses->where('zone_id',$o->id);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -85,6 +86,8 @@ class System extends Model
|
||||
return sprintf('RC-%s-%05d',$o->zone->domain->name,$o->region_id);
|
||||
|
||||
case DomainController::NODE_NC;
|
||||
return sprintf('NC-%s-%05d',$o->zone->domain->name,$o->host_id);
|
||||
|
||||
case DomainController::NODE_HC;
|
||||
case NULL:
|
||||
default:
|
||||
|
@@ -25,7 +25,10 @@ class Zone extends Model
|
||||
|
||||
public function addresses()
|
||||
{
|
||||
return $this->hasMany(Address::class);
|
||||
return $this->hasMany(Address::class)
|
||||
->active()
|
||||
->FTNorder()
|
||||
->with(['system.sessions','system.setup','zone.domain']);
|
||||
}
|
||||
|
||||
public function domain()
|
||||
|
Reference in New Issue
Block a user