2021-06-17 14:08:30 +00:00
< ? php
namespace App\Http\Controllers ;
2021-08-25 12:13:49 +00:00
use Carbon\Carbon ;
2023-09-08 14:07:46 +00:00
use Illuminate\Database\QueryException ;
2021-06-17 14:08:30 +00:00
use Illuminate\Http\Request ;
2021-08-08 07:27:22 +00:00
use Illuminate\Support\Arr ;
2023-07-23 07:27:52 +00:00
use Illuminate\Support\Collection ;
2021-11-11 11:57:13 +00:00
use Illuminate\Support\Facades\Auth ;
2022-03-14 11:28:54 +00:00
use Illuminate\Support\Facades\DB ;
2023-08-03 07:30:52 +00:00
use Illuminate\Support\Facades\Log ;
2022-03-14 11:28:54 +00:00
use Illuminate\Support\Facades\Notification ;
2021-11-11 11:57:13 +00:00
use Illuminate\Support\ViewErrorBag ;
2021-06-17 14:08:30 +00:00
2023-08-03 07:30:52 +00:00
use App\Classes\FTN\Message ;
2023-09-08 14:07:46 +00:00
use App\Http\Requests\ { AddressMerge , AreafixRequest , SystemRegister };
2023-07-26 09:44:07 +00:00
use App\Jobs\AddressPoll ;
2024-04-13 10:54:05 +00:00
use App\Models\ { Address , Echoarea , Echomail , Filearea , Netmail , Setup , System , Zone };
2023-07-23 07:27:52 +00:00
use App\Notifications\Netmails\AddressLink ;
2021-07-01 14:25:41 +00:00
use App\Rules\ { FidoInteger , TwoByteInteger };
2021-06-17 14:08:30 +00:00
class SystemController extends Controller
{
2023-08-03 07:30:52 +00:00
private const LOGKEY = 'CSC' ;
2023-10-05 11:15:53 +00:00
/**
* Add or edit a node
*/
public function add_edit ( SystemRegister $request , System $o )
{
$this -> authorize ( 'update' , $o );
if ( $request -> post ()) {
2023-11-26 02:10:23 +00:00
foreach ([ 'name' , 'location' , 'sysop' , 'hold' , 'phone' , 'address' , 'port' , 'active' , 'method' , 'notes' , 'zt_id' , 'pkt_type' , 'heartbeat' ] as $key )
2023-10-05 11:15:53 +00:00
$o -> { $key } = $request -> post ( $key );
switch ( $request -> post ( 'pollmode' )) {
case 1 : $o -> pollmode = FALSE ; break ;
case 2 : $o -> pollmode = TRUE ; break ;
default : $o -> pollmode = NULL ;
}
$o -> autohold = FALSE ;
$o -> save ();
$mailers = collect ( $request -> post ( 'mailer_details' ))
-> filter ( function ( $item ) { return $item [ 'port' ]; })
-> transform ( function ( $item ) { $item [ 'active' ] = Arr :: get ( $item , 'active' , FALSE ); return $item ; });
$o -> mailers () -> sync ( $mailers );
2023-12-20 06:18:10 +00:00
if ( $request -> post ( 'users' )) {
if ( array_filter ( $request -> post ( 'users' ), function ( $item ) { return $item ; }))
$o -> users () -> sync ( $request -> post ( 'users' ));
else
$o -> users () -> detach ();
}
2023-10-05 11:15:53 +00:00
2023-10-05 12:28:18 +00:00
return redirect () -> to ( 'system' );
2023-10-05 11:15:53 +00:00
}
$o -> load ([ 'addresses.zone.domain' , 'addresses.system' , 'sessions.domain' , 'sessions.systems' ]);
return view ( 'system.addedit' )
-> with ( 'action' , $o -> exists ? 'update' : 'create' )
-> with ( 'o' , $o );
}
2021-06-20 13:03:20 +00:00
/**
* Add an address to a system
*
* @ param Request $request
* @ param System $o
* @ return \Illuminate\Http\RedirectResponse
* @ throws \Illuminate\Auth\Access\AuthorizationException
*/
2023-10-05 11:15:53 +00:00
public function address_add ( Request $request , System $o )
2021-06-20 13:03:20 +00:00
{
2021-07-04 11:47:23 +00:00
// @todo This should be admin of the zone
2021-06-20 13:03:20 +00:00
$this -> authorize ( 'admin' , $o );
2021-08-25 12:13:49 +00:00
session () -> flash ( 'accordion' , 'address' );
2021-06-20 13:03:20 +00:00
$request -> validate ([
2023-07-29 03:17:36 +00:00
'action' => 'required|in:region,host,node,update' ,
2021-06-20 13:03:20 +00:00
'zone_id' => 'required|exists:zones,id' ,
]);
2024-05-05 12:47:33 +00:00
switch ( $request -> action ) {
2021-06-20 13:03:20 +00:00
case 'region' :
$request -> validate ([
'region_id_new' => [
'required' ,
new TwoByteInteger ,
2024-05-05 12:47:33 +00:00
function ( $attribute , $value , $fail ) use ( $request ) {
2021-06-20 13:03:20 +00:00
// Check that the region doesnt already exist
$o = Address :: where ( function ( $query ) use ( $value ) {
2024-05-05 12:47:33 +00:00
return $query -> where ( function ( $query ) use ( $value ) {
return $query
-> where ( 'region_id' , $value )
-> where ( 'role' , Address :: NODE_RC );
})
// Check that a host doesnt already exist
-> orWhere ( function ( $query ) use ( $value ) {
return $query
-> where ( 'host_id' , $value )
-> where ( 'role' , Address :: NODE_NC );
});
})
-> where ( 'zone_id' , $request -> zone_id )
-> where ( 'node_id' , 0 )
-> where ( 'point_id' , 0 );
2021-06-20 13:03:20 +00:00
if ( $o -> count ()) {
$fail ( 'Region or host already exists' );
}
},
],
]);
$oo = new Address ;
2024-05-05 12:47:33 +00:00
$oo -> zone_id = $request -> zone_id ;
$oo -> region_id = $request -> region_id_new ;
$oo -> host_id = $request -> region_id_new ;
2021-06-20 13:03:20 +00:00
$oo -> node_id = 0 ;
$oo -> point_id = 0 ;
$oo -> active = TRUE ;
$o -> addresses () -> save ( $oo );
break ;
case 'host' :
$request -> validate ([
2021-07-01 14:25:41 +00:00
'region_id' => [ 'required' , new FidoInteger ],
2021-06-20 13:03:20 +00:00
'host_id_new' => [
'required' ,
new TwoByteInteger ,
2021-07-05 13:17:00 +00:00
function ( $attribute , $value , $fail ) use ( $request ) {
2021-06-20 13:03:20 +00:00
// Check that the region doesnt already exist
$o = Address :: where ( function ( $query ) use ( $value ) {
2021-07-18 13:38:18 +00:00
return $query -> where ( function ( $query ) use ( $value ) {
2024-05-05 12:47:33 +00:00
return $query
-> where ( 'region_id' , $value )
2022-01-24 11:56:13 +00:00
-> where ( 'role' , Address :: NODE_RC );
2021-07-18 13:38:18 +00:00
})
2023-10-05 11:15:53 +00:00
// Check that a host doesnt already exist
-> orWhere ( function ( $query ) use ( $value ) {
2024-05-05 12:47:33 +00:00
return $query
-> where ( 'host_id' , $value )
2023-10-05 11:15:53 +00:00
-> where ( 'role' , Address :: NODE_NC );
});
2021-07-05 13:17:00 +00:00
})
2024-05-05 12:47:33 +00:00
-> where ( 'zone_id' , $request -> zone_id )
2024-05-09 11:22:30 +00:00
-> where ( 'node_id' , $request -> node_id_new )
2024-05-05 12:47:33 +00:00
-> where ( 'point_id' , 0 );
2021-06-20 13:03:20 +00:00
if ( $o -> count ()) {
$fail ( 'Region or host already exists' );
}
},
],
'node_id_new' => [
'required' ,
new TwoByteInteger ,
function ( $attribute , $value , $fail ) use ( $request ) {
// Check that the region doesnt already exist
$o = Address :: where ( function ( $query ) use ( $request , $value ) {
return $query
2024-05-05 12:47:33 +00:00
-> where ( 'zone_id' , $request -> zone_id )
-> where ( 'host_id' , $request -> host_id_new )
2021-06-20 13:03:20 +00:00
-> where ( 'node_id' , $value )
-> where ( 'point_id' , 0 )
2022-01-24 11:56:13 +00:00
-> where ( 'role' , Address :: NODE_RC );
2021-06-20 13:03:20 +00:00
});
if ( $o -> count ()) {
$fail ( 'Host already exists' );
}
},
]
]);
2021-07-26 11:21:58 +00:00
// 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 ,
2022-01-24 11:56:13 +00:00
'role' => Address :: NODE_NC ,
2021-07-26 11:21:58 +00:00
]);
}
$oo -> system_id = $request -> system_id ;
$oo -> active = TRUE ;
$o -> addresses () -> save ( $oo );
2021-06-20 13:03:20 +00:00
$oo = new Address ;
2024-05-05 12:47:33 +00:00
$oo -> zone_id = $request -> zone_id ;
$oo -> region_id = $request -> region_id ;
$oo -> host_id = $request -> host_id_new ;
$oo -> node_id = $request -> node_id_new ;
2021-06-20 13:03:20 +00:00
$oo -> point_id = 0 ;
$oo -> active = TRUE ;
$o -> addresses () -> save ( $oo );
break ;
2023-07-29 03:17:36 +00:00
case 'update' :
2021-06-20 13:03:20 +00:00
case 'node' :
$request -> validate ([
2021-07-01 14:25:41 +00:00
'region_id' => [ 'required' , new FidoInteger ],
'host_id' => [ 'required' , new FidoInteger ],
2021-06-20 13:03:20 +00:00
'node_id' => [
'required' ,
new TwoByteInteger ,
function ( $attribute , $value , $fail ) use ( $request ) {
2023-04-15 10:24:53 +00:00
if ( $request -> point_id === 0 ) {
// Check that the host doesnt already exist
$o = Address :: where ( function ( $query ) use ( $request , $value ) {
return $query
2024-05-05 12:47:33 +00:00
-> where ( 'zone_id' , $request -> zone_id )
-> where ( 'host_id' , $request -> host_id )
2023-04-15 10:24:53 +00:00
-> where ( 'node_id' , $value )
2023-07-29 03:17:36 +00:00
-> where ( 'point_id' , 0 )
2024-05-05 12:47:33 +00:00
-> where ( 'id' , '<>' , $request -> submit );
2023-04-15 10:24:53 +00:00
});
if ( $o -> count ()) {
$fail ( sprintf ( 'Host already exists: %s' , $o -> get () -> pluck ( 'ftn' ) -> join ( ',' )));
}
}
},
],
'point_id' => [
'required' ,
function ( $attribute , $value , $fail ) use ( $request ) {
2024-04-12 05:29:11 +00:00
if ( ! is_numeric ( $value ) || $value > Address :: ADDRESS_FIELD_MAX )
$fail ( sprintf ( 'Point numbers must be between 0 and %d' , Address :: ADDRESS_FIELD_MAX ));
2023-04-15 10:24:53 +00:00
// Check that the host doesnt already exist
2021-06-20 13:03:20 +00:00
$o = Address :: where ( function ( $query ) use ( $request , $value ) {
return $query
2024-05-05 12:47:33 +00:00
-> where ( 'zone_id' , $request -> zone_id )
-> where ( 'host_id' , $request -> host_id )
-> where ( 'node_id' , $request -> node_id )
2023-07-29 03:17:36 +00:00
-> where ( 'point_id' , $value )
2024-05-05 12:47:33 +00:00
-> where ( 'id' , '<>' , $request -> submit );
2021-06-20 13:03:20 +00:00
});
if ( $o -> count ()) {
2023-04-15 10:24:53 +00:00
$fail ( sprintf ( 'Point already exists: %s' , $o -> get () -> pluck ( 'ftn' ) -> join ( ',' )));
2021-06-20 13:03:20 +00:00
}
2023-04-15 10:24:53 +00:00
}
2021-06-20 13:03:20 +00:00
],
'hub' => 'required|boolean' ,
2021-06-25 06:42:12 +00:00
'hub_id' => 'nullable|exists:addresses,id' ,
2023-07-29 03:17:36 +00:00
'security' => 'required|integer|min:0|max:7' ,
2021-06-20 13:03:20 +00:00
]);
2024-05-05 12:47:33 +00:00
$oo = Address :: findOrNew ( $request -> submit );
$oo -> zone_id = $request -> zone_id ;
$oo -> region_id = $request -> region_id ;
$oo -> host_id = $request -> host_id ;
$oo -> node_id = $request -> node_id ;
$oo -> point_id = $request -> point_id ;
2024-05-09 11:22:30 +00:00
// @todo Validation should check that the hub is in the right region and net
2024-05-05 12:47:33 +00:00
$oo -> hub_id = $request -> hub_id > 0 ? $request -> hub_id : NULL ;
$oo -> security = $request -> security ;
2021-06-20 13:03:20 +00:00
$oo -> active = TRUE ;
$o -> addresses () -> save ( $oo );
break ;
default :
2024-05-05 12:47:33 +00:00
return redirect () -> back () -> withErrors ([ 'action' => 'Unknown action: ' . $request -> action ]);
2021-06-20 13:03:20 +00:00
}
2023-10-05 11:15:53 +00:00
return redirect () -> to ( sprintf ( 'system/addedit/%d' , $o -> id ));
2021-06-20 13:03:20 +00:00
}
2021-07-04 11:47:23 +00:00
/**
2023-10-05 11:15:53 +00:00
* Delete address assigned to a host
2021-07-04 11:47:23 +00:00
*
2023-10-05 11:15:53 +00:00
* @ param Address $o
2021-07-04 11:47:23 +00:00
* @ return \Illuminate\Http\RedirectResponse
* @ throws \Illuminate\Auth\Access\AuthorizationException
*/
2023-10-05 11:15:53 +00:00
public function address_del ( Address $o )
2021-07-04 11:47:23 +00:00
{
// @todo This should be admin of the zone
2023-10-05 11:15:53 +00:00
$this -> authorize ( 'admin' , $o );
session () -> flash ( 'accordion' , 'address' );
2021-08-13 12:53:59 +00:00
2023-10-05 11:15:53 +00:00
$sid = $o -> system_id ;
$o -> active = FALSE ;
$o -> save ();
$o -> delete ();
2021-07-04 11:47:23 +00:00
2023-10-05 11:15:53 +00:00
return redirect () -> to ( sprintf ( 'system/addedit/%d' , $sid ));
2021-07-04 11:47:23 +00:00
}
2021-06-17 14:08:30 +00:00
/**
2023-10-05 11:15:53 +00:00
* Demote an address NC -> node
*
* @ param Address $o
* @ return \Illuminate\Http\RedirectResponse
* @ throws \Illuminate\Auth\Access\AuthorizationException
2021-06-17 14:08:30 +00:00
*/
2023-10-05 11:15:53 +00:00
public function address_dem ( Address $o )
2021-06-17 14:08:30 +00:00
{
2023-10-05 11:15:53 +00:00
// @todo This should be admin of the zone
$this -> authorize ( 'admin' , $o );
session () -> flash ( 'accordion' , 'address' );
2023-07-07 13:59:04 +00:00
2023-10-05 11:15:53 +00:00
// Make sure that no other system has this address active.
2024-05-09 11:22:30 +00:00
if ( $o -> role_id === Address :: NODE_NN )
2024-04-22 04:27:48 +00:00
return redirect () -> back () -> withErrors ([ 'address' => sprintf ( '%s cannot be demoted any more' , $o -> ftn3D )]);
2021-06-17 14:08:30 +00:00
2024-05-09 11:22:30 +00:00
$off = $o -> role_id ;
$o -> role &= ~ $off ;
$o -> role |= ( $off << 1 );
2023-10-05 11:15:53 +00:00
$o -> save ();
2021-07-26 11:21:58 +00:00
2023-10-05 11:15:53 +00:00
return redirect () -> to ( sprintf ( 'system/addedit/%d' , $o -> system_id ));
2021-06-17 14:08:30 +00:00
}
2023-09-08 14:07:46 +00:00
public function address_merge ( AddressMerge $request , int $id )
{
if ( $request -> validated ()) {
DB :: beginTransaction ();
2024-04-13 10:54:05 +00:00
// Find all the echomails that have both seenby's
$x = Echomail :: select ([ 'id' ])
-> join ( 'echomail_seenby' ,[ 'echomail_seenby.echomail_id' => 'echomails.id' ])
-> whereIn ( 'address_id' ,[ $request -> src ])
-> distinct ()
2024-05-05 22:23:07 +00:00
-> with ([ 'seenby' => function ( $query ) use ( $request ) {
return $query
-> select ( 'id' )
-> whereIn ( 'address_id' ,[ $request -> src , $request -> dst ]);
}])
2024-04-13 10:54:05 +00:00
-> get ()
-> filter ( function ( $item ) use ( $request ) {
return $item -> seenby -> contains ( $request -> dst ) && $item -> seenby -> contains ( $request -> src );
});
// If the Echomail has both source and dest, delete the src
if ( $x -> count ())
DB :: table ( 'echomail_seenby' )
-> where ( 'address_id' , $request -> src )
-> whereIn ( 'echomail_id' , $x -> pluck ( 'id' ))
-> delete ();
2023-09-08 14:07:46 +00:00
// Find all echomail seenbys
$x = DB :: update ( 'update echomail_seenby set address_id=? where address_id=?' ,[ $request -> dst , $request -> src ]);
// Find all echomail paths
$x = DB :: update ( 'update echomail_path set address_id=? where address_id=?' ,[ $request -> dst , $request -> src ]);
// Find all echomails
$x = DB :: update ( 'update echomails set fftn_id=? where fftn_id=?' ,[ $request -> dst , $request -> src ]);
// Find all netmails
$x = DB :: update ( 'update netmails set fftn_id=? where fftn_id=?' ,[ $request -> dst , $request -> src ]);
// Find all netmails
$x = DB :: update ( 'update netmails set tftn_id=? where tftn_id=?' ,[ $request -> dst , $request -> src ]);
// Find all nodelist
$x = DB :: update ( 'update address_nodelist set address_id=? where address_id=?' ,[ $request -> dst , $request -> src ]);
// Find all file seenbys
$x = DB :: update ( 'update file_seenby set address_id=? where address_id=?' ,[ $request -> dst , $request -> src ]);
// Find all files
$x = DB :: update ( 'update files set fftn_id=? where fftn_id=?' ,[ $request -> dst , $request -> src ]);
$src = Address :: withTrashed () -> findOrFail ( $request -> src );
// Resubscribe echoareas
try {
$x = DB :: update ( 'update address_echoarea set address_id=? where address_id=?' ,[ $request -> dst , $request -> src ]);
} catch ( QueryException $e ) {
DB :: rollback ();
return back () -> withInput () -> withErrors ( 'error' , sprintf ( 'You may need to remove %s:%s (%d) from echoareas' , $src -> ftn , $src -> system -> name , $src -> id ));
}
// Resubscribe fileareas
try {
$x = DB :: update ( 'update address_filearea set address_id=? where address_id=?' ,[ $request -> dst , $request -> src ]);
} catch ( QueryException $e ) {
DB :: rollback ();
return back () -> withInput () -> withErrors ( 'error' , sprintf ( 'You may need to remove %s:%s (%d) from fileareas' , $src -> ftn , $src -> system -> name , $src -> id ));
}
if ( $src -> forceDelete ()) {
DB :: commit ();
return redirect () -> to ( 'address/merge/' . $request -> dst );
} else {
return back () -> withInput () -> withErrors ( 'error' , sprintf ( 'Address [%s] didnt delete?' , $src -> ftn ));
DB :: rollBack ();
}
}
$o = Address :: withTrashed ()
-> findOrFail ( $id );
$oo = Address :: withTrashed ()
-> where ( 'zone_id' , $o -> zone_id )
-> where ( 'host_id' , $o -> host_id )
-> where ( 'node_id' , $o -> node_id )
-> where ( 'point_id' , $o -> point_id )
-> get ();
2023-09-11 12:57:29 +00:00
if ( $o -> zone -> domain -> flatten )
$oo = $oo -> merge ( Address :: withTrashed ()
-> whereIn ( 'zone_id' , $o -> zone -> domain -> zones -> pluck ( 'id' ))
-> where ( 'host_id' , $o -> host_id )
-> where ( 'node_id' , $o -> node_id )
-> where ( 'point_id' , $o -> point_id )
-> get ()
);
2023-09-08 14:07:46 +00:00
return view ( 'system/address-merge' )
-> with ( 'o' , $o )
-> with ( 'oo' , $oo );
}
2023-10-05 11:15:53 +00:00
/**
* Move address to another system
*
* @ param Request $request
* @ param System $so
* @ param Address $o
* @ return \Illuminate\Contracts\Foundation\Application | \Illuminate\Contracts\View\Factory | \Illuminate\Contracts\View\View | \Illuminate\Http\RedirectResponse
* @ throws \Illuminate\Auth\Access\AuthorizationException
*/
public function address_mov ( Request $request , System $so , Address $o )
{
session () -> flash ( 'accordion' , 'address' );
// Quick check that this address belongs to this system
if ( $so -> addresses -> search ( function ( $item ) use ( $o ) { return $item -> id === $o -> id ; }) === FALSE )
abort ( 404 );
if ( $request -> post ()) {
$this -> authorize ( 'admin' , $o );
$validated = $request -> validate ([
'system_id' => 'required|exists:systems,id' ,
'remove' => 'nullable|boolean' ,
'remsess' => 'nullable|boolean|exclude_if:remove,1' ,
]);
$o -> system_id = $validated [ 'system_id' ];
$o -> save ();
if ( Arr :: get ( $validated , 'remove' )) {
$so -> sessions () -> detach ( $o -> zone );
$so -> mailers () -> detach ();
$so -> users () -> detach ();
$so -> delete ();
} elseif ( Arr :: get ( $validated , 'remsess' )) {
$so -> sessions () -> detach ( $o -> zone );
}
return redirect () -> to ( 'system/addedit/' . $validated [ 'system_id' ]);
}
return view ( 'system.moveaddr' )
-> with ( 'o' , $o );
}
/**
* Promote an address node -> NC
*
* @ param Address $o
* @ return \Illuminate\Http\RedirectResponse
* @ throws \Illuminate\Auth\Access\AuthorizationException
*/
public function address_pro ( Address $o )
{
// @todo This should be admin of the zone
$this -> authorize ( 'admin' , $o );
session () -> flash ( 'accordion' , 'address' );
// Make sure that no other system has this address active.
2024-05-09 11:22:30 +00:00
if ( $o -> role_id === Address :: NODE_NC )
2024-04-22 04:27:48 +00:00
return redirect () -> back () -> withErrors ([ 'address' => sprintf ( '%s cannot be promoted any more' , $o -> ftn3D )]);
2023-10-05 11:15:53 +00:00
2024-05-09 11:22:30 +00:00
$off = $o -> role_id ;
$o -> role &= ~ $off ;
$o -> role |= ( $off >> 1 );
2023-10-05 11:15:53 +00:00
$o -> save ();
return redirect () -> to ( sprintf ( 'system/addedit/%d' , $o -> system_id ));
}
/**
* Recover a deleted address
*
* @ param int $id
* @ return \Illuminate\Http\RedirectResponse
* @ throws \Illuminate\Auth\Access\AuthorizationException
*/
public function address_pur ( int $id )
{
$o = Address :: onlyTrashed () -> findOrFail ( $id );
// @todo This should be admin of the zone
$this -> authorize ( 'admin' , $o );
session () -> flash ( 'accordion' , 'address' );
$o -> forceDelete ();
return redirect () -> to ( sprintf ( 'system/addedit/%d' , $o -> system_id ));
}
/**
* Recover a deleted address
*
* @ param int $id
* @ return \Illuminate\Http\RedirectResponse
* @ throws \Illuminate\Auth\Access\AuthorizationException
*/
public function address_rec ( int $id )
{
$o = Address :: onlyTrashed () -> findOrFail ( $id );
// @todo This should be admin of the zone
$this -> authorize ( 'admin' , $o );
session () -> flash ( 'accordion' , 'address' );
$o -> restore ();
return redirect () -> to ( sprintf ( 'system/addedit/%d' , $o -> system_id ));
}
/**
* Suspend address assigned to a host
*
* @ param Address $o
* @ return \Illuminate\Http\RedirectResponse
* @ throws \Illuminate\Auth\Access\AuthorizationException
*/
public function address_sus ( Address $o )
{
// @todo This should be admin of the zone
$this -> authorize ( 'admin' , $o );
session () -> flash ( 'accordion' , 'address' );
// Make sure that no other system has this address active.
if ( ! $o -> active && ( $x = Address :: where ([
'zone_id' => $o -> zone_id ,
'host_id' => $o -> host_id ,
'node_id' => $o -> node_id ,
'point_id' => $o -> point_id ,
'active' => TRUE ,
]) -> single ())) {
2024-04-22 04:27:48 +00:00
return redirect () -> back () -> withErrors ([ 'address' => sprintf ( '%s is already active on system [<a href="%s">%s</a>]' , $o -> ftn , url ( 'system/addedit' , $x -> system_id ), $x -> system -> name )]);
2023-10-05 11:15:53 +00:00
}
$o -> active = ( ! $o -> active );
$o -> save ();
return redirect () -> to ( sprintf ( 'system/addedit/%d' , $o -> system_id ));
}
2022-01-04 13:34:33 +00:00
public function api_address ( Request $request , System $o ) : Collection
{
2023-07-19 06:51:40 +00:00
return Address :: select ([ 'addresses.id' , 'addresses.zone_id' , 'region_id' , 'host_id' , 'node_id' , 'point_id' ])
2022-01-04 13:34:33 +00:00
-> leftjoin ( 'zones' ,[ 'zones.id' => 'addresses.zone_id' ])
-> where ( 'addresses.system_id' , $o -> id )
-> where ( 'zones.domain_id' , $request -> domain_id )
2022-11-20 00:47:46 +00:00
-> withTrashed ()
2022-01-04 13:34:33 +00:00
-> FTNorder ()
-> get ()
2023-07-19 06:51:40 +00:00
-> map ( function ( $item ) { return [ 'id' => ( string ) $item -> id , 'value' => $item -> ftn4d ]; });
2022-01-04 13:34:33 +00:00
}
2023-07-29 03:17:36 +00:00
public function api_address_get ( Address $o )
{
return $o ;
}
2022-03-14 11:28:54 +00:00
/**
* Identify all the addresses from systems that are not owned by a user
*
* @ param Request $request
* @ return Collection
*/
2023-10-05 11:15:53 +00:00
public function api_address_orphan ( Request $request ) : Collection
2022-03-14 11:28:54 +00:00
{
$result = collect ();
list ( $zone_id , $host_id , $node_id , $point_id , $domain ) = sscanf ( $request -> query ( 'term' ), '%d:%d/%d.%d@%s' );
# Look for Systems
foreach ( Address :: select ([ 'addresses.id' , 'systems.name' , DB :: raw ( 'systems.id AS system_id' ), 'zones.zone_id' , 'region_id' , 'host_id' , 'node_id' , 'point_id' , 'addresses.zone_id' ])
-> join ( 'zones' ,[ 'zones.id' => 'addresses.zone_id' ])
-> rightjoin ( 'systems' ,[ 'systems.id' => 'addresses.system_id' ])
-> when ( $zone_id || $host_id || $node_id , function ( $query ) use ( $zone_id , $host_id , $node_id ) {
return $query
-> when ( $zone_id , function ( $q , $zone_id ) { return $q -> where ( 'zones.zone_id' , $zone_id ); })
-> where ( function ( $q ) use ( $host_id ) {
return $q
-> when ( $host_id , function ( $q , $host_id ) { return $q -> where ( 'region_id' , $host_id ); })
-> when ( $host_id , function ( $q , $host_id ) { return $q -> orWhere ( 'host_id' , $host_id ); });
})
-> when ( $node_id , function ( $q , $node_id ) { return $q -> where ( 'node_id' , $node_id ); });
})
-> orWhere ( 'systems.name' , 'ilike' , '%' . $request -> query ( 'term' ) . '%' )
-> orderBy ( 'systems.name' )
-> get () as $o )
{
$result -> push ([ 'id' => $o -> id , 'name' => sprintf ( '%s (%s)' , $o -> ftn3d , $o -> name ), 'category' => 'Systems' ]);
}
return $result ;
}
2024-05-04 14:10:55 +00:00
public function api_address_validated_toggle ( Request $request , string $state ) : array
{
$o = Address :: findOrFail ( $request -> id );
$o -> validated = $state === 'off' ? FALSE : TRUE ;
$o -> save ();
Log :: debug ( sprintf ( '%s:- Address Validated set to [%s]' , self :: LOGKEY , $o -> autohold ? 'ON' : 'OFF' ));
return [ 'validated' => $o -> validated ];
}
public function api_autohold_toggle ( Request $request , string $state ) : array
{
$o = System :: findOrFail ( $request -> id );
$o -> autohold = $state === 'off' ? FALSE : TRUE ;
$o -> save ();
Log :: debug ( sprintf ( '%s:- Autohold set to [%s]' , self :: LOGKEY , $o -> autohold ? 'ON' : 'OFF' ));
return [ 'autohold' => $o -> autohold ];
}
2023-08-03 07:30:52 +00:00
public function areafix ( AreafixRequest $request , System $o , Zone $zo )
{
if ( $request -> post ()) {
$no = new Netmail ;
foreach ( $request -> safe () as $item => $value )
$no -> { $item } = $value ;
$no -> from = auth :: user () -> name ;
$no -> msg .= " \r " ;
$no -> datetime = Carbon :: now ();
$no -> tzoffset = $no -> datetime -> utcOffset ();
$no -> flags = ( Message :: FLAG_LOCAL | Message :: FLAG_PRIVATE | Message :: FLAG_CRASH );
$no -> cost = 0 ;
$no -> tearline = sprintf ( '%s (%04X)' , Setup :: PRODUCT_NAME , Setup :: PRODUCT_ID );
$no -> save ();
2023-09-19 03:54:35 +00:00
Log :: info ( sprintf ( '%s:= Areafix to [%s], scheduling a poll' , self :: LOGKEY , $no -> tftn -> ftn ));
2023-08-03 07:30:52 +00:00
AddressPoll :: dispatch ( $no -> tftn );
return redirect () -> back () -> with ( 'success' , 'Areafix/Filefix sent' );
}
return view ( 'system.areafix' )
-> with ( 'zo' , $zo )
-> with ( 'ao' , $o -> match ( $zo ) -> first ())
-> with ( 'o' , $o )
-> with ( 'setup' , Setup :: findOrFail ( config ( 'app.id' )));
}
2021-08-25 12:13:49 +00:00
/**
* Update the systems echoareas
*
* @ param Request $request
* @ param System $o
2021-09-06 13:39:32 +00:00
* @ return \Illuminate\Contracts\Foundation\Application | \Illuminate\Contracts\View\Factory | \Illuminate\Contracts\View\View | \Illuminate\Http\RedirectResponse
2021-08-25 12:13:49 +00:00
*/
public function echoareas ( Request $request , System $o )
{
2022-01-04 13:34:33 +00:00
$ao = $o -> addresses -> firstWhere ( 'id' , $request -> address_id );
2021-08-25 12:13:49 +00:00
2023-06-27 07:39:11 +00:00
if (( $request -> method () === 'POST' ) && $request -> post ()) {
2021-08-25 12:13:49 +00:00
session () -> flash ( 'accordion' , 'echoarea' );
2022-11-20 00:47:46 +00:00
if ( $ao -> trashed () && collect ( $request -> get ( 'id' )) -> diff ( $ao -> echoareas -> pluck ( 'id' )) -> count ())
return redirect () -> back () -> withErrors ( sprintf ( 'Address [%s] has been deleted, cannot add additional echos' , $ao -> ftn3d ));
2021-08-25 12:13:49 +00:00
// Ensure we have session details for this address.
if ( ! $ao -> session ( 'sespass' ))
return redirect () -> back () -> withErrors ( 'System doesnt belong to this network' );
2022-01-04 13:34:33 +00:00
$ao -> echoareas () -> syncWithPivotValues ( $request -> get ( 'id' ,[]),[ 'subscribed' => Carbon :: now ()]);
2021-08-25 12:13:49 +00:00
2023-06-27 07:39:11 +00:00
return redirect () -> back () -> with ( 'success' , 'Echoareas updated' );
2021-08-25 12:13:49 +00:00
}
2023-09-16 14:14:46 +00:00
// @todo Allow a NC/RC/ZC to override
2021-08-25 12:13:49 +00:00
$eo = Echoarea :: active ()
2022-01-04 13:34:33 +00:00
-> where ( 'domain_id' , $ao -> zone -> domain_id )
2023-09-16 14:14:46 +00:00
-> where ( function ( $query ) use ( $ao ) {
return $query
-> whereRaw ( sprintf ( '(security&7) <= %d' , $ao -> security )) // write
-> orWhereRaw ( sprintf ( '((security>>3)&7) <= %d' , $ao -> security )); // read
})
2021-08-25 12:13:49 +00:00
-> orderBy ( 'name' )
-> get ();
return view ( 'system.widget.echoarea' )
-> with ( 'o' , $o )
-> with ( 'ao' , $ao )
-> with ( 'echoareas' , $eo );
}
2022-11-01 11:24:36 +00:00
/**
* Update the systems fileareas
*
* @ param Request $request
* @ param System $o
* @ return \Illuminate\Contracts\Foundation\Application | \Illuminate\Contracts\View\Factory | \Illuminate\Contracts\View\View | \Illuminate\Http\RedirectResponse
*/
public function fileareas ( Request $request , System $o )
{
$ao = $o -> addresses -> firstWhere ( 'id' , $request -> address_id );
2023-06-27 07:39:11 +00:00
if (( $request -> method () === 'POST' ) && $request -> post ()) {
2022-11-01 11:24:36 +00:00
session () -> flash ( 'accordion' , 'filearea' );
// Ensure we have session details for this address.
if ( ! $ao -> session ( 'sespass' ))
return redirect () -> back () -> withErrors ( 'System doesnt belong to this network' );
$ao -> fileareas () -> syncWithPivotValues ( $request -> get ( 'id' ,[]),[ 'subscribed' => Carbon :: now ()]);
2023-06-27 07:39:11 +00:00
return redirect () -> back () -> with ( 'success' , 'Fileareas updated' );
2022-11-01 11:24:36 +00:00
}
2023-09-16 14:14:46 +00:00
// @todo Allow a NC/RC/ZC to override
2022-11-01 11:24:36 +00:00
$fo = Filearea :: active ()
-> where ( 'domain_id' , $ao -> zone -> domain_id )
2023-09-16 14:14:46 +00:00
-> where ( function ( $query ) use ( $ao ) {
return $query
-> whereRaw ( sprintf ( '(security&7) <= %d' , $ao -> security )) // write
-> orWhereRaw ( sprintf ( '((security>>3)&7) <= %d' , $ao -> security )); // read
})
2022-11-01 11:24:36 +00:00
-> orderBy ( 'name' )
-> get ();
return view ( 'system.widget.filearea' )
-> with ( 'o' , $o )
-> with ( 'ao' , $ao )
-> with ( 'fileareas' , $fo );
}
2021-08-08 07:27:22 +00:00
/**
2023-10-05 11:15:53 +00:00
* Register a system , or link to an existing system
2021-08-08 07:27:22 +00:00
*/
2023-10-05 11:15:53 +00:00
public function register ( SystemRegister $request )
2021-08-08 07:27:22 +00:00
{
2023-10-05 11:15:53 +00:00
// Step 1, show the user a form to select an existing defined system
if ( $request -> isMethod ( 'GET' ))
return view ( 'user.system.register' );
2021-08-08 07:27:22 +00:00
2023-10-05 11:15:53 +00:00
if ( $request -> action === 'register' && $request -> name && is_numeric ( $request -> name ))
return view ( 'user.system.widget.register_confirm' )
-> with ( 'o' , System :: findOrFail ( $request -> name ));
2021-08-08 07:27:22 +00:00
2023-10-05 11:15:53 +00:00
$o = System :: findOrNew ( is_numeric ( $request -> system_id ) ? $request -> system_id : NULL );
2021-08-08 07:27:22 +00:00
2023-10-05 11:15:53 +00:00
// 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 );
2021-08-08 07:27:22 +00:00
2023-10-05 11:15:53 +00:00
// 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 );
2021-08-08 07:27:22 +00:00
}
2023-10-05 11:15:53 +00:00
return view ( 'user.system.widget.register_send' )
-> with ( 'validate' , $validate )
-> with ( 'o' , $o );
2021-08-08 07:27:22 +00:00
}
2023-10-05 11:15:53 +00:00
// If the system doesnt exist, we'll create it
if ( ! $o -> exist ) {
$o -> sysop = Auth :: user () -> name ;
2021-08-08 07:27:22 +00:00
2023-10-05 11:15:53 +00:00
foreach ([ 'name' , 'zt_id' , 'location' , 'phone' , 'method' , 'address' , 'port' ] as $item )
if ( $request -> { $item })
$o -> { $item } = $request -> { $item };
2021-07-04 11:47:23 +00:00
2023-10-05 11:15:53 +00:00
$o -> active = TRUE ;
}
2023-07-06 08:43:32 +00:00
2023-10-05 11:15:53 +00:00
if ( $request -> post ( 'submit' )) {
Auth :: user () -> systems () -> save ( $o );
2023-07-06 08:43:32 +00:00
2023-10-05 11:15:53 +00:00
// @todo if the system already exists and part of one of our networks, we'll need to send the registration email to confirm the address.
// @todo mark the system (or addresses) as "pending" at this stage until it is confirmed
return redirect () -> to ( url ( 'system/addedit' , $o -> id ));
}
2023-07-06 08:43:32 +00:00
2023-10-05 11:15:53 +00:00
// Re-flash our previously input data
if ( $request -> old )
session () -> flashInput ( $request -> old );
2024-04-26 02:23:55 +00:00
return view ( 'system.widget.system' )
2023-10-05 11:15:53 +00:00
-> with ( 'action' , $request -> action )
-> with ( 'o' , $o )
-> with ( 'errors' , new ViewErrorBag );
2023-07-06 08:43:32 +00:00
}
2021-07-01 14:25:41 +00:00
/**
2023-10-05 11:15:53 +00:00
* Add Session details
2021-07-01 14:25:41 +00:00
*
2023-10-05 11:15:53 +00:00
* @ param Request $request
* @ param System $o
2021-07-01 14:25:41 +00:00
* @ return \Illuminate\Http\RedirectResponse
* @ throws \Illuminate\Auth\Access\AuthorizationException
*/
2023-10-05 11:15:53 +00:00
public function session_add ( Request $request , System $o )
2021-07-01 14:25:41 +00:00
{
2021-07-04 11:47:23 +00:00
// @todo This should be admin of the zone
2023-10-05 11:15:53 +00:00
$this -> authorize ( 'update' , $o );
session () -> flash ( 'accordion' , 'session' );
2021-07-01 14:25:41 +00:00
2023-10-05 11:15:53 +00:00
$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' ,
'fixpass' => 'required|string|min:4' ,
]);
2021-07-01 14:25:41 +00:00
2023-10-05 11:15:53 +00:00
$zo = Zone :: findOrFail ( $validate [ 'zone_id' ]);
2022-11-19 01:02:13 +00:00
2023-12-18 21:54:26 +00:00
/*
// @todo Disabling this, it needs improvement. If the new node is the ZC it becomes the default for the zone (and therefore remove all defaults from other addresses in the same zone), otherwise default should be false
2023-10-05 11:15:53 +00:00
// If this session is for the ZC, it now becomes the default.
if ( $o -> match ( $zo , Address :: NODE_ZC ) -> count ()) {
SystemZone :: where ( 'default' , TRUE ) -> update ([ 'default' => FALSE ]);
$validate [ 'default' ] = TRUE ;
}
2023-12-18 21:54:26 +00:00
*/
2022-11-19 01:02:13 +00:00
2023-10-05 11:15:53 +00:00
$o -> sessions () -> attach ( $zo , $validate );
2022-11-19 01:02:13 +00:00
2023-10-05 11:15:53 +00:00
return redirect () -> to ( sprintf ( 'system/addedit/%d' , $o -> id ));
2022-11-19 01:02:13 +00:00
}
/**
2023-10-05 11:15:53 +00:00
* Delete address assigned to a host
2022-11-19 01:02:13 +00:00
*
2023-10-05 11:15:53 +00:00
* @ param Address $o
2022-11-19 01:02:13 +00:00
* @ return \Illuminate\Http\RedirectResponse
* @ throws \Illuminate\Auth\Access\AuthorizationException
*/
2023-10-05 11:15:53 +00:00
public function session_del ( System $o , Zone $zo )
2022-11-19 01:02:13 +00:00
{
2023-10-05 11:15:53 +00:00
$this -> authorize ( 'admin' , $zo );
session () -> flash ( 'accordion' , 'session' );
2022-11-19 01:02:13 +00:00
2023-10-05 11:15:53 +00:00
$o -> sessions () -> detach ( $zo );
2022-11-19 01:02:13 +00:00
2023-10-05 11:15:53 +00:00
return redirect () -> to ( sprintf ( 'system/addedit/%d' , $o -> id ));
2022-11-19 01:02:13 +00:00
}
2023-08-10 01:09:55 +00:00
// @todo Can this be consolidated with system_register()
2023-10-05 11:15:53 +00:00
2022-12-04 02:30:38 +00:00
public function system_link ( Request $request )
{
if ( ! $request -> system_id )
return redirect ( 'user/system/register' );
$so = System :: findOrFail ( $request -> system_id );
$ca = NULL ;
$la = NULL ;
2023-12-18 04:13:16 +00:00
foreach ( our_address () as $ao ) {
2022-12-11 09:17:24 +00:00
if (( $ca = $so -> match ( $ao -> zone )) -> count ())
2022-12-04 02:30:38 +00:00
break ;
}
2023-07-26 09:44:07 +00:00
if ( $ca -> count () && $la = $ca -> pop ()) {
2023-07-23 07:27:52 +00:00
Notification :: route ( 'netmail' , $la ) -> notify ( new AddressLink ( Auth :: user ()));
2023-07-26 09:44:07 +00:00
AddressPoll :: dispatch ( $la ) -> delay ( 15 );
}
2022-12-04 02:30:38 +00:00
return view ( 'user.system.register_send' )
-> with ( 'la' , $la )
-> with ( 'o' , $so );
}
2022-11-25 10:44:03 +00:00
public function view ( System $o )
{
2023-04-15 03:34:08 +00:00
$o -> load ([ 'addresses' ]);
2022-11-25 10:44:03 +00:00
return view ( 'system.view' )
-> with ( 'o' , $o );
}
2022-03-14 11:28:54 +00:00
}