Work on registration of existing systems to users
This commit is contained in:
parent
d68307461e
commit
8072f7c5a9
@ -36,6 +36,7 @@ class Page
|
|||||||
$this->logo = new ANSI;
|
$this->logo = new ANSI;
|
||||||
$this->left_box = new Font;
|
$this->left_box = new Font;
|
||||||
$this->crlf = $crlf;
|
$this->crlf = $crlf;
|
||||||
|
$this->text = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __get($key)
|
public function __get($key)
|
||||||
@ -114,7 +115,8 @@ class Page
|
|||||||
*/
|
*/
|
||||||
public function addText(string $text,bool $right=FALSE)
|
public function addText(string $text,bool $right=FALSE)
|
||||||
{
|
{
|
||||||
$this->text = $text;
|
$this->text .= $text;
|
||||||
|
|
||||||
$this->text_right = $right;
|
$this->text_right = $right;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,11 +7,13 @@ use Illuminate\Support\Collection;
|
|||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Arr;
|
use Illuminate\Support\Arr;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Illuminate\Support\Facades\Gate;
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Illuminate\Support\Facades\Notification;
|
||||||
use Illuminate\Support\ViewErrorBag;
|
use Illuminate\Support\ViewErrorBag;
|
||||||
|
|
||||||
use App\Http\Requests\SystemRegister;
|
use App\Http\Requests\SystemRegister;
|
||||||
use App\Models\{Address,Echoarea,System,SystemZone,Zone};
|
use App\Models\{Address,Echoarea,Setup,System,SystemZone,Zone};
|
||||||
|
use App\Notifications\AddressLink;
|
||||||
use App\Rules\{FidoInteger,TwoByteInteger};
|
use App\Rules\{FidoInteger,TwoByteInteger};
|
||||||
|
|
||||||
class SystemController extends Controller
|
class SystemController extends Controller
|
||||||
@ -258,6 +260,8 @@ class SystemController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function add_edit(SystemRegister $request,System $o)
|
public function add_edit(SystemRegister $request,System $o)
|
||||||
{
|
{
|
||||||
|
$this->authorize('update',$o);
|
||||||
|
|
||||||
if ($request->post()) {
|
if ($request->post()) {
|
||||||
foreach (['name','location','sysop','hold','phone','address','port','active','method','notes','mailer_type','mailer_address','mailer_port','zt_id'] as $key)
|
foreach (['name','location','sysop','hold','phone','address','port','active','method','notes','mailer_type','mailer_address','mailer_port','zt_id'] as $key)
|
||||||
$o->{$key} = $request->post($key);
|
$o->{$key} = $request->post($key);
|
||||||
@ -269,11 +273,9 @@ class SystemController extends Controller
|
|||||||
|
|
||||||
$o->load(['addresses.zone.domain']);
|
$o->load(['addresses.zone.domain']);
|
||||||
|
|
||||||
return Gate::check('update',$o)
|
return view('system.addedit')
|
||||||
? view('system.addedit')
|
|
||||||
->with('action',$o->exists ? 'update' : 'create')
|
->with('action',$o->exists ? 'update' : 'create')
|
||||||
->with('o',$o)
|
->with('o',$o);
|
||||||
: redirect()->to('user/system/register');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function api_address(Request $request,System $o): Collection
|
public function api_address(Request $request,System $o): Collection
|
||||||
@ -300,6 +302,42 @@ class SystemController extends Controller
|
|||||||
->get();
|
->get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Identify all the addresses from systems that are not owned by a user
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @return Collection
|
||||||
|
*/
|
||||||
|
public function api_orphan_address(Request $request): Collection
|
||||||
|
{
|
||||||
|
$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;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete address assigned to a host
|
* Delete address assigned to a host
|
||||||
*
|
*
|
||||||
@ -450,8 +488,26 @@ class SystemController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function system_register(SystemRegister $request)
|
public function system_register(SystemRegister $request)
|
||||||
{
|
{
|
||||||
|
// Step 1, show the user a form to select an existing defined system
|
||||||
|
if ($request->isMethod('GET'))
|
||||||
|
return view('user.system.register');
|
||||||
|
|
||||||
$o = System::findOrNew($request->system_id);
|
$o = System::findOrNew($request->system_id);
|
||||||
|
|
||||||
|
// If the system exists, and we are 'register', we'll start the address claim process
|
||||||
|
if ($o->exists && $request->action == 'register') {
|
||||||
|
$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($x,Auth::user()));
|
||||||
|
|
||||||
|
return view('user.system.widget.register_confirm')
|
||||||
|
->with('validate',$validate)
|
||||||
|
->with('o',$o);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the system doesnt exist, we'll create it
|
||||||
if (! $o->exist) {
|
if (! $o->exist) {
|
||||||
$o->sysop = Auth::user()->name;
|
$o->sysop = Auth::user()->name;
|
||||||
|
|
||||||
@ -479,4 +535,4 @@ class SystemController extends Controller
|
|||||||
->with('o',$o)
|
->with('o',$o)
|
||||||
->with('errors',new ViewErrorBag);
|
->with('errors',new ViewErrorBag);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -5,8 +5,9 @@ namespace App\Http\Controllers;
|
|||||||
use Illuminate\Auth\Events\Registered;
|
use Illuminate\Auth\Events\Registered;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Illuminate\Support\Facades\Validator;
|
||||||
|
|
||||||
use App\Models\User;
|
use App\Models\{Address,User};
|
||||||
|
|
||||||
class UserController extends Controller
|
class UserController extends Controller
|
||||||
{
|
{
|
||||||
@ -63,6 +64,36 @@ class UserController extends Controller
|
|||||||
return view('user.home');
|
return view('user.home');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function link(Request $request)
|
||||||
|
{
|
||||||
|
if ($request->post()) {
|
||||||
|
$request->validate([
|
||||||
|
'address_id'=>'required|exists:addresses,id',
|
||||||
|
'code'=>'required:string',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$ao = Address::findOrFail($request->address_id);
|
||||||
|
if ($ao->check_activation(Auth::user(),$request->code)) {
|
||||||
|
$ao->validated = TRUE;
|
||||||
|
$ao->save();
|
||||||
|
|
||||||
|
$ao->system->users()->save(Auth::user());
|
||||||
|
|
||||||
|
return redirect()->to('/');
|
||||||
|
|
||||||
|
} else {
|
||||||
|
$validator = Validator::make([],[]);
|
||||||
|
$validator->errors()->add(
|
||||||
|
'code', 'Invalid Code!'
|
||||||
|
);
|
||||||
|
|
||||||
|
return back()->withErrors($validator);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return view('user.link');
|
||||||
|
}
|
||||||
|
|
||||||
public function register()
|
public function register()
|
||||||
{
|
{
|
||||||
return view('user/system/register');
|
return view('user/system/register');
|
||||||
|
@ -21,7 +21,7 @@ class SystemRegister extends FormRequest
|
|||||||
{
|
{
|
||||||
$this->so = System::findOrNew($request->system_id);
|
$this->so = System::findOrNew($request->system_id);
|
||||||
|
|
||||||
return Gate::allows($this->so->exists ? 'update' : 'create',$this->so);
|
return Gate::allows($this->so->users->count() ? 'update' : 'register',$this->so);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -31,7 +31,7 @@ class SystemRegister extends FormRequest
|
|||||||
*/
|
*/
|
||||||
public function rules(Request $request)
|
public function rules(Request $request)
|
||||||
{
|
{
|
||||||
if (! $request->isMethod('post'))
|
if ((! $request->isMethod('post')) || ($request->action == 'register'))
|
||||||
return [];
|
return [];
|
||||||
|
|
||||||
if ((! $this->so->exists) && ($request->action == 'create')) {
|
if ((! $this->so->exists) && ($request->action == 'create')) {
|
||||||
|
@ -7,6 +7,7 @@ use Exception;
|
|||||||
use Illuminate\Database\Eloquent\Collection;
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
|
use Illuminate\Support\Facades\Crypt;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
@ -369,6 +370,41 @@ class Address extends Model
|
|||||||
return ($o && $o->system->active) ? $o : NULL;
|
return ($o && $o->system->active) ? $o : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an activation code for this address
|
||||||
|
*
|
||||||
|
* @param User $uo
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function set_activation(User $uo): string
|
||||||
|
{
|
||||||
|
return sprintf('%x:%s',
|
||||||
|
$this->id,
|
||||||
|
substr(md5(sprintf('%d:%x',$uo->id,timew($this->updated_at))),0,10)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check the user's activation code for this address is correct
|
||||||
|
*
|
||||||
|
* @param User $uo
|
||||||
|
* @param string $code
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function check_activation(User $uo,string $code): bool
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
Log::info(sprintf('%s:Checking Activation code [%s] invalid for user [%d]',self::LOGKEY,$code,$uo->id));
|
||||||
|
|
||||||
|
return ($code == $this->set_activation($uo));
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
Log::error(sprintf('%s:! Activation code [%s] invalid for user [%d]',self::LOGKEY,$code,$uo->id));
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Netmail waiting to be sent to this system
|
* Netmail waiting to be sent to this system
|
||||||
*
|
*
|
||||||
|
@ -9,13 +9,13 @@ use Illuminate\Support\Facades\Log;
|
|||||||
|
|
||||||
use App\Classes\FTN\Message;
|
use App\Classes\FTN\Message;
|
||||||
use App\Interfaces\Packet;
|
use App\Interfaces\Packet;
|
||||||
use App\Traits\EncodeUTF8;
|
use App\Traits\{EncodeUTF8,MsgID};
|
||||||
|
|
||||||
final class Netmail extends Model implements Packet
|
final class Netmail extends Model implements Packet
|
||||||
{
|
{
|
||||||
private const LOGKEY = 'MN-';
|
private const LOGKEY = 'MN-';
|
||||||
|
|
||||||
use SoftDeletes,EncodeUTF8;
|
use SoftDeletes,EncodeUTF8,MsgID;
|
||||||
|
|
||||||
private const cast_utf8 = [
|
private const cast_utf8 = [
|
||||||
'to',
|
'to',
|
||||||
|
@ -8,7 +8,9 @@ use Illuminate\Database\Eloquent\Model;
|
|||||||
use Illuminate\Support\Facades\File;
|
use Illuminate\Support\Facades\File;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class Setup
|
* This class represents our configuration.
|
||||||
|
*
|
||||||
|
* Our 'System' is defined by system_id, and from it we can find out our BBS name and addresses.
|
||||||
*
|
*
|
||||||
* @package App\Models
|
* @package App\Models
|
||||||
* @property Collection nodes
|
* @property Collection nodes
|
||||||
@ -47,37 +49,6 @@ class Setup extends Model
|
|||||||
// Our non model attributes and values
|
// Our non model attributes and values
|
||||||
private array $internal = [];
|
private array $internal = [];
|
||||||
|
|
||||||
public static function product_id(int $c=self::PRODUCT_ID): string
|
|
||||||
{
|
|
||||||
return hexstr($c);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* RELATIONS */
|
|
||||||
|
|
||||||
public function system()
|
|
||||||
{
|
|
||||||
return $this->belongsTo(System::class);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ATTRIBUTES */
|
|
||||||
|
|
||||||
public function getLocationAttribute()
|
|
||||||
{
|
|
||||||
return $this->system->location;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getSysopAttribute()
|
|
||||||
{
|
|
||||||
return $this->system->sysop;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getSystemNameAttribute()
|
|
||||||
{
|
|
||||||
return $this->system->name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* METHODS */
|
|
||||||
|
|
||||||
public function __construct(array $attributes = [])
|
public function __construct(array $attributes = [])
|
||||||
{
|
{
|
||||||
parent::__construct($attributes);
|
parent::__construct($attributes);
|
||||||
@ -143,6 +114,49 @@ class Setup extends Model
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Mailer Product ID in hex.
|
||||||
|
*
|
||||||
|
* @param int $c
|
||||||
|
* @return string
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public static function product_id(int $c=self::PRODUCT_ID): string
|
||||||
|
{
|
||||||
|
return hexstr($c);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* RELATIONS */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The defined system that this setup is valid for
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||||
|
*/
|
||||||
|
public function system()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(System::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ATTRIBUTES */
|
||||||
|
|
||||||
|
public function getLocationAttribute()
|
||||||
|
{
|
||||||
|
return $this->system->location;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSysopAttribute()
|
||||||
|
{
|
||||||
|
return $this->system->sysop;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSystemNameAttribute()
|
||||||
|
{
|
||||||
|
return $this->system->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* METHODS */
|
||||||
|
|
||||||
/* BINKP OPTIONS: BINKP_OPT_* */
|
/* BINKP OPTIONS: BINKP_OPT_* */
|
||||||
|
|
||||||
public function binkpOptionClear(int $key): void
|
public function binkpOptionClear(int $key): void
|
||||||
|
@ -133,4 +133,20 @@ class System extends Model
|
|||||||
return $item->role & $type;
|
return $item->role & $type;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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_ACTIVE|Address::NODE_PVT|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);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
104
app/Notifications/AddressLink.php
Normal file
104
app/Notifications/AddressLink.php
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Notifications;
|
||||||
|
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Notifications\Notification;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
|
use App\Classes\{ANSI,Fonts\Thin,Page};
|
||||||
|
use App\Classes\Fonts\Thick;
|
||||||
|
use App\Classes\FTN\Message;
|
||||||
|
use App\Models\{Address,Netmail,Setup,User};
|
||||||
|
|
||||||
|
class AddressLink extends Notification //implements ShouldQueue
|
||||||
|
{
|
||||||
|
private const LOGKEY = 'NAL';
|
||||||
|
|
||||||
|
use Queueable;
|
||||||
|
|
||||||
|
private Address $ao;
|
||||||
|
private User $uo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a netmail to enable a sysop to activate an address.
|
||||||
|
*
|
||||||
|
* @param Address $ao
|
||||||
|
* @param User $uo
|
||||||
|
*/
|
||||||
|
public function __construct(Address $ao,User $uo)
|
||||||
|
{
|
||||||
|
$this->queue = 'netmail';
|
||||||
|
$this->ao = $ao;
|
||||||
|
$this->uo = $uo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the notification's delivery channels.
|
||||||
|
*
|
||||||
|
* @param mixed $notifiable
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function via($notifiable)
|
||||||
|
{
|
||||||
|
return ['netmail'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the mail representation of the notification.
|
||||||
|
*
|
||||||
|
* @param mixed $notifiable
|
||||||
|
* @return Netmail
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
|
public function toNetmail($notifiable): Netmail
|
||||||
|
{
|
||||||
|
Log::info(sprintf('%s:Sending a link code for address [%s]',self::LOGKEY,$this->ao->ftn));
|
||||||
|
|
||||||
|
$so = Setup::findOrFail(config('app.id'))->system;
|
||||||
|
|
||||||
|
$o = new Netmail;
|
||||||
|
$o->to = $this->ao->system->sysop;
|
||||||
|
$o->from = Setup::PRODUCT_NAME;
|
||||||
|
$o->subject = 'Address Link Code';
|
||||||
|
$o->datetime = Carbon::now();
|
||||||
|
$o->tzoffset = $o->datetime->utcOffset();
|
||||||
|
|
||||||
|
$o->fftn_id = $so->match($this->ao->zone)->first()->id;
|
||||||
|
$o->tftn_id = $this->ao->id;
|
||||||
|
$o->flags = Message::FLAG_LOCAL;
|
||||||
|
$o->cost = 0;
|
||||||
|
|
||||||
|
$o->tagline = 'Address Linking...';
|
||||||
|
$o->tearline = sprintf('%s (%04X)',Setup::PRODUCT_NAME,Setup::PRODUCT_ID);
|
||||||
|
|
||||||
|
// Message
|
||||||
|
$msg = new Page;
|
||||||
|
$msg->addLogo(new ANSI(base_path('public/logo/netmail.bin')));
|
||||||
|
|
||||||
|
$header = new Thick;
|
||||||
|
$header->addText(ANSI::ansi_code([1,37]).'Clearing Houz');
|
||||||
|
$msg->addHeader($header,'FTN Mailer and Tosser',TRUE,0xc4);
|
||||||
|
|
||||||
|
$lbc = new Thin;
|
||||||
|
$lbc->addText('#link');
|
||||||
|
$msg->addLeftBoxContent($lbc);
|
||||||
|
|
||||||
|
$msg->addText(sprintf(
|
||||||
|
"Hi %s,\r\r".
|
||||||
|
"This message is to link your address [%s] to your user ID in the Clearing Houz web site.\r\r".
|
||||||
|
"If you didnt start this process, then you can safely ignore this netmail. But if you wanted to link this address, please head over to [%s] and paste in the following:\r\r%s\r",
|
||||||
|
$this->ao->system->sysop,
|
||||||
|
$this->ao->ftn3d,
|
||||||
|
url('/link'),
|
||||||
|
$this->ao->set_activation($this->uo)
|
||||||
|
));
|
||||||
|
|
||||||
|
$o->msg = $msg->render();
|
||||||
|
$o->save();
|
||||||
|
|
||||||
|
return $o;
|
||||||
|
}
|
||||||
|
}
|
@ -34,7 +34,7 @@ class NetmailChannel
|
|||||||
*
|
*
|
||||||
* @param mixed $notifiable
|
* @param mixed $notifiable
|
||||||
* @param \Illuminate\Notifications\Notification $notification
|
* @param \Illuminate\Notifications\Notification $notification
|
||||||
* @return \Psr\Http\Message\ResponseInterface|null
|
* @return \Psr\Http\Message\ResponseInterface|void
|
||||||
*/
|
*/
|
||||||
public function send($notifiable,Notification $notification)
|
public function send($notifiable,Notification $notification)
|
||||||
{
|
{
|
||||||
@ -42,9 +42,8 @@ class NetmailChannel
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
$o = $notification->toNetmail($notifiable);
|
$o = $notification->toNetmail($notifiable);
|
||||||
Log::info(sprintf('%s:Test Netmail created [%s]',self::LOGKEY,$o->id));
|
|
||||||
|
|
||||||
Job::dispatch($ao);
|
Job::dispatch($ao);
|
||||||
Log::info(sprintf('%s:Dispatched job to pool address [%s]',self::LOGKEY,$ao->ftn));
|
Log::info(sprintf('%s:Sent netmail [%s] via [%s]',self::LOGKEY,$o->msgid,$ao->ftn));
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -64,7 +64,7 @@ class NetmailTest extends Notification //implements ShouldQueue
|
|||||||
$o->datetime = Carbon::now();
|
$o->datetime = Carbon::now();
|
||||||
$o->tzoffset = $o->datetime->utcOffset();
|
$o->tzoffset = $o->datetime->utcOffset();
|
||||||
|
|
||||||
$o->fftn_id = $so->match($this->ao->zone)->first();
|
$o->fftn_id = $so->match($this->ao->zone)->first()->id;
|
||||||
$o->tftn_id = $this->ao->id;
|
$o->tftn_id = $this->ao->id;
|
||||||
$o->flags = Message::FLAG_LOCAL;
|
$o->flags = Message::FLAG_LOCAL;
|
||||||
$o->cost = 0;
|
$o->cost = 0;
|
||||||
|
@ -26,6 +26,18 @@ class SystemPolicy
|
|||||||
return ($user->isAdmin() || (! $system->exists));
|
return ($user->isAdmin() || (! $system->exists));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Can the user register this system
|
||||||
|
*
|
||||||
|
* @param User $user
|
||||||
|
* @param System $system
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function register(User $user,System $system): bool
|
||||||
|
{
|
||||||
|
return ! $system->users->count() || $system->users->has($user);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine whether the user can update the model.
|
* Determine whether the user can update the model.
|
||||||
*
|
*
|
||||||
|
32
database/migrations/2021_11_26_114344_add_validated.php
Normal file
32
database/migrations/2021_11_26_114344_add_validated.php
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
class AddValidated extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::table('addresses', function (Blueprint $table) {
|
||||||
|
$table->boolean('validated')->default(FALSE);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::table('addresses', function (Blueprint $table) {
|
||||||
|
$table->dropColumn('validated');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -13,7 +13,10 @@
|
|||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<p>This system is aware of the following systems @can('create',(new \App\Models\System))(you can <a href="{{ url('ftn/system/addedit') }}">add</a> more)@endcan:</p>
|
<p>This system is aware of the following systems
|
||||||
|
@can('create',(new \App\Models\System))(you can <a href="{{ url('user/system/register') }}">register</a> more):@endcan
|
||||||
|
@can('admin',(new \App\Models\System))(you can <a href="{{ url('ftn/system/addedit') }}">add</a> more):@endcan
|
||||||
|
</p>
|
||||||
|
|
||||||
@if (\App\Models\System::active()->count() == 0)
|
@if (\App\Models\System::active()->count() == 0)
|
||||||
@can('create',(new \App\Models\System))
|
@can('create',(new \App\Models\System))
|
||||||
@ -39,7 +42,7 @@
|
|||||||
<tbody>
|
<tbody>
|
||||||
@foreach (\App\Models\System::active()->with(['addresses.zone.domain'])->get() as $oo)
|
@foreach (\App\Models\System::active()->with(['addresses.zone.domain'])->get() as $oo)
|
||||||
<tr>
|
<tr>
|
||||||
<td><a href="{{ url('ftn/system/addedit',[$oo->id]) }}">{{ $oo->id }}</a></td>
|
<td><a href="{{ url('ftn/system/addedit',[$oo->id]) }}" @cannot('update',$oo)class="disabled" @endcannot>{{ $oo->id }}</a></td>
|
||||||
<td>{{ $oo->name }} @if(! $oo->active)<span class="float-end"><small>[i]</small></span>@endif</td>
|
<td>{{ $oo->name }} @if(! $oo->active)<span class="float-end"><small>[i]</small></span>@endif</td>
|
||||||
<td>{{ $oo->sysop }}</td>
|
<td>{{ $oo->sysop }}</td>
|
||||||
<td>{{ $oo->location }}</td>
|
<td>{{ $oo->location }}</td>
|
||||||
@ -72,7 +75,7 @@
|
|||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
$('table tr').click(function() {
|
$('table tr').click(function() {
|
||||||
var href = $(this).find('a').attr('href');
|
var href = $(this).find('a:not(.disabled)').attr('href');
|
||||||
|
|
||||||
if (href)
|
if (href)
|
||||||
window.location = href;
|
window.location = href;
|
||||||
|
178
resources/views/user/link.blade.php
Normal file
178
resources/views/user/link.blade.php
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
@extends('layouts.app')
|
||||||
|
@section('htmlheader_title')
|
||||||
|
Link
|
||||||
|
@endsection
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
<form class="row g-0 needs-validation" method="post" novalidate>
|
||||||
|
@csrf
|
||||||
|
|
||||||
|
<input type="hidden" id="address_id" name="address_id">
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="greyframe titledbox shadow0xb0">
|
||||||
|
<h2 class="cap">Enter your Link code</h2>
|
||||||
|
|
||||||
|
<!-- ADDRESS -->
|
||||||
|
<div class="row" style="z-index: 2;">
|
||||||
|
<div class="col-4">
|
||||||
|
<label for="address" class="form-label">Address</label>
|
||||||
|
<div class="input-group has-validation">
|
||||||
|
<span class="input-group-text"><i class="bi bi-globe"></i></span>
|
||||||
|
<input type="text" class="form-control @error('address_id') is-invalid @enderror" id="address" placeholder="Address" name="address" value="{{ old('address') }}" required autofocus autocomplete="off">
|
||||||
|
<span id="search-icon" style="z-index: 4;width: 0;"><i style="border-radius: 50%;" class="spinner-border spinner-border-sm text-dark d-none"></i></span>
|
||||||
|
<div id="address_search_results"></div>
|
||||||
|
<span class="invalid-feedback" role="alert">
|
||||||
|
@error('address_id')
|
||||||
|
{{ $message }}
|
||||||
|
@else
|
||||||
|
A address is required.
|
||||||
|
@enderror
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- CODE -->
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-4">
|
||||||
|
<label for="code" class="form-label">Code</label>
|
||||||
|
<div class="input-group has-validation">
|
||||||
|
<span class="input-group-text"><i class="bi bi-fingerprint"></i></span>
|
||||||
|
<input type="text" class="form-control @error('code') is-invalid @enderror" id="code" placeholder="Code" name="code" value="{{ old('code') }}" required>
|
||||||
|
<span class="invalid-feedback" role="alert">
|
||||||
|
@error('code')
|
||||||
|
{{ $message }}
|
||||||
|
@else
|
||||||
|
A code is required.
|
||||||
|
@enderror
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
<a href="{{ url('home') }}" class="btn btn-danger">Cancel</a>
|
||||||
|
<button type="submit" name="submit" class="btn btn-success float-end">Validate</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
@endsection
|
||||||
|
|
||||||
|
@section('page-css')
|
||||||
|
<style>
|
||||||
|
input#address + span {
|
||||||
|
left: -1.5em;
|
||||||
|
top: 0.5em;
|
||||||
|
position:relative
|
||||||
|
}
|
||||||
|
div#address_search_results ul {
|
||||||
|
color:#eeeeee;
|
||||||
|
background-color:#292929;
|
||||||
|
font-size: .85rem;
|
||||||
|
padding: 0 5px 0 5px;
|
||||||
|
z-index: 99;
|
||||||
|
top: -0.5em;
|
||||||
|
left: 31em !important;
|
||||||
|
}
|
||||||
|
div#address_search_results ul li.dropdown-header {
|
||||||
|
display: block;
|
||||||
|
color: #fff !important;
|
||||||
|
}
|
||||||
|
div#address_search_results ul li,
|
||||||
|
div#address_search_results ul li a {
|
||||||
|
display: block;
|
||||||
|
color: #aaa !important;
|
||||||
|
margin: 0 !important;
|
||||||
|
border: 0 !important;
|
||||||
|
width: inherit;
|
||||||
|
text-indent: 0 !important;
|
||||||
|
padding-left: 0 !important;
|
||||||
|
}
|
||||||
|
div#address_search_results ul li:hover {
|
||||||
|
padding-left: 0;
|
||||||
|
text-indent: 0;
|
||||||
|
}
|
||||||
|
div#address_search_results ul li:before {
|
||||||
|
content:""!important
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
@append
|
||||||
|
@section('page-scripts')
|
||||||
|
<script type="text/javascript">
|
||||||
|
|
||||||
|
var address_id;
|
||||||
|
var addresssearch = _.debounce(function(url,query,process,icon){
|
||||||
|
icon = $('#search-icon').find('i');
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url : url,
|
||||||
|
type : 'GET',
|
||||||
|
data : 'term=' + query,
|
||||||
|
dataType : 'JSON',
|
||||||
|
async : true,
|
||||||
|
cache : false,
|
||||||
|
beforeSend : function() {
|
||||||
|
if (c++ == 0) {
|
||||||
|
icon.removeClass('d-none');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
success : function(data) {
|
||||||
|
// if json is null, means no match, won't do again.
|
||||||
|
if(data==null || (data.length===0)) return;
|
||||||
|
|
||||||
|
process(data);
|
||||||
|
},
|
||||||
|
complete : function() {
|
||||||
|
if (--c == 0) {
|
||||||
|
icon.addClass('d-none');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}, 500);
|
||||||
|
|
||||||
|
$(document).ready(function() {
|
||||||
|
$('input[id=address]').typeahead({
|
||||||
|
autoSelect: false,
|
||||||
|
scrollHeight: 10,
|
||||||
|
theme: 'bootstrap5',
|
||||||
|
delay: 500,
|
||||||
|
minLength: 3,
|
||||||
|
items: {{ $search_limit ?? 5 }},
|
||||||
|
fitToElement: false,
|
||||||
|
selectOnBlur: false,
|
||||||
|
appendTo: "#address_search_results",
|
||||||
|
source: function (query,process) {
|
||||||
|
addresssearch('{{ url('api/addresses/orphan') }}',query,process);
|
||||||
|
},
|
||||||
|
|
||||||
|
matcher: function () { return true; },
|
||||||
|
|
||||||
|
// Disable sorting and just return the items (items should by the ajax method)
|
||||||
|
sorter: function(items) {
|
||||||
|
return items;
|
||||||
|
},
|
||||||
|
|
||||||
|
updater: function (item) {
|
||||||
|
console.log(item);
|
||||||
|
$('#address_id').val(item.id);
|
||||||
|
console.log($('#address_id'));
|
||||||
|
return item.name;
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.on('keyup keypress', function(event) {
|
||||||
|
var key = event.keyCode || event.which;
|
||||||
|
if (key === 13) {
|
||||||
|
event.preventDefault();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
@endsection
|
@ -119,7 +119,7 @@
|
|||||||
$.ajax({
|
$.ajax({
|
||||||
url : '{{ url('user/system/register') }}',
|
url : '{{ url('user/system/register') }}',
|
||||||
type : 'POST',
|
type : 'POST',
|
||||||
data : { system_id: system_id,name: $('#name').val(),action: 'create',old: {!! json_encode(old()) !!} },
|
data : { system_id: system_id,name: $('#name').val(),action: 'register',old: {!! json_encode(old()) !!} },
|
||||||
dataType : 'json',
|
dataType : 'json',
|
||||||
async : true,
|
async : true,
|
||||||
cache : false,
|
cache : false,
|
||||||
|
@ -0,0 +1,13 @@
|
|||||||
|
<!-- $o = System::class -->
|
||||||
|
<form class="row g-0 needs-validation" method="post" autocomplete="off" novalidate>
|
||||||
|
@csrf
|
||||||
|
|
||||||
|
@if($validate->count())
|
||||||
|
<p>OK, here's what we are going to do. I'm going to send you a routed netmail with a code - please follow the instructions
|
||||||
|
in that netmail.</p>
|
||||||
|
<p>Once the code is validated, this system will be assigned to you.</p>
|
||||||
|
@else
|
||||||
|
<p>I cant validate that <strong class="highlight">{{ $o->name }}</strong> is your system, we share now common zones.</p>
|
||||||
|
<p>You might want to talk to an admin.</p>
|
||||||
|
@endif
|
||||||
|
</form>
|
@ -21,6 +21,7 @@ Route::middleware(['auth:api'])->group(function () {
|
|||||||
Route::get('hosts/{o}/{region}',[DomainController::class,'api_hosts'])
|
Route::get('hosts/{o}/{region}',[DomainController::class,'api_hosts'])
|
||||||
->where('o','[0-9]+');
|
->where('o','[0-9]+');
|
||||||
Route::get('systems/orphan',[SystemController::class,'api_orphan']);
|
Route::get('systems/orphan',[SystemController::class,'api_orphan']);
|
||||||
|
Route::get('addresses/orphan',[SystemController::class,'api_orphan_address']);
|
||||||
Route::get('hubs/{o}/{host}',[DomainController::class,'api_hubs'])
|
Route::get('hubs/{o}/{host}',[DomainController::class,'api_hubs'])
|
||||||
->where('o','[0-9]+');
|
->where('o','[0-9]+');
|
||||||
Route::post('default/{o}',[ZoneController::class,'api_default'])
|
Route::post('default/{o}',[ZoneController::class,'api_default'])
|
||||||
|
@ -40,8 +40,9 @@ Route::get('admin/switch/stop',[UserSwitchController::class,'user_switch_stop'])
|
|||||||
Route::get('/',[HomeController::class,'home']);
|
Route::get('/',[HomeController::class,'home']);
|
||||||
Route::view('about','about');
|
Route::view('about','about');
|
||||||
|
|
||||||
Route::middleware(['verified','activeuser'])->group(function () {
|
Route::middleware(['auth','verified','activeuser'])->group(function () {
|
||||||
Route::get('dashboard',[UserController::class,'dashboard']);
|
Route::get('dashboard',[UserController::class,'dashboard']);
|
||||||
|
Route::match(['get','post'],'link',[UserController::class,'link']);
|
||||||
|
|
||||||
Route::get('ftn/domain',[DomainController::class,'home']);
|
Route::get('ftn/domain',[DomainController::class,'home']);
|
||||||
Route::match(['get','post'],'ftn/domain/addedit/{o?}',[DomainController::class,'add_edit'])
|
Route::match(['get','post'],'ftn/domain/addedit/{o?}',[DomainController::class,'add_edit'])
|
||||||
@ -82,8 +83,7 @@ Route::middleware(['verified','activeuser'])->group(function () {
|
|||||||
Route::match(['get','post'],'ftn/zone/addedit/{o?}',[ZoneController::class,'add_edit'])
|
Route::match(['get','post'],'ftn/zone/addedit/{o?}',[ZoneController::class,'add_edit'])
|
||||||
->where('o','[0-9]+');
|
->where('o','[0-9]+');
|
||||||
|
|
||||||
Route::get('user/system/register',[UserController::class,'register']);
|
Route::match(['get','post'],'user/system/register',[SystemController::class,'system_register']);
|
||||||
Route::post('user/system/register',[SystemController::class,'system_register']);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
Route::get('network/{o}',[HomeController::class,'network']);
|
Route::get('network/{o}',[HomeController::class,'network']);
|
||||||
|
Loading…
Reference in New Issue
Block a user