Added System, fixed something with Domain, added 403, start of some other items

This commit is contained in:
Deon George 2021-06-18 00:08:30 +10:00
parent 1e7c05cb90
commit 491d3d55c3
17 changed files with 451 additions and 16 deletions

View File

@ -0,0 +1,38 @@
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\Models\User;
class MakeAdmin extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'make:admin {email : User Email}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Make a user a system admin';
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
$o = User::where('email',$this->argument('email'))->firstOrfail();
$o->admin = ! $o->admin;
$o->save();
$this->info(sprintf('User [%s] %s an admin',$o->email,$o->admin ? 'IS' : 'is NOT'));
}
}

View File

@ -20,8 +20,8 @@ class DomainController extends Controller
{ {
if ($request->post()) { if ($request->post()) {
$request->validate([ $request->validate([
'name' => 'required|max:8|unique:domains,name,'.$o->id, 'name' => 'required|max: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->id, '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', 'active' => 'required',
'public' => 'required', 'public' => 'required',
]); ]);

View File

@ -2,6 +2,8 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use Illuminate\Support\Facades\Auth;
use App\Models\Domain; use App\Models\Domain;
class HomeController extends Controller class HomeController extends Controller
@ -12,6 +14,15 @@ class HomeController extends Controller
->with('o',$o); ->with('o',$o);
} }
/**
* Render a view that summarises the users permissions
*/
public function permissions()
{
return view('auth.permissions')
->with('user',Auth::user());
}
/** /**
* System Setup * System Setup
* *
@ -19,6 +30,6 @@ class HomeController extends Controller
*/ */
public function setup() public function setup()
{ {
return view('setup');
} }
} }

View File

@ -0,0 +1,46 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\System;
class SystemController extends Controller
{
public function __construct()
{
$this->middleware('auth');
}
/**
* Add or edit a node
*/
public function add_edit(Request $request,System $o)
{
if ($request->post()) {
$request->validate([
'name' => 'required|min:3|unique:systems,name,'.($o->exists ? $o->id : 0),
'location' => 'required|min:3',
'sysop' => 'required|min:3',
'address' => 'nullable|regex:/^(?!:\/\/)(?=.{1,255}$)((.{1,63}\.){1,127}(?![0-9]*$)[a-z0-9-]+\.?)$/i',
'port' => 'nullable|digits_between:2,5',
]);
foreach (['name','location','sysop','address','port','active','method','notes'] as $key)
$o->{$key} = $request->post($key);
$o->save();
return redirect()->action([self::class,'home']);
}
return view('system.addedit')
->with('o',$o);
}
public function home()
{
return view('system.home');
}
}

View File

@ -0,0 +1,42 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\User;
class UserController extends Controller
{
public function __construct()
{
$this->middleware('can:admin');
}
/**
* Add or edit a node
*/
public function add_edit(Request $request,User $o)
{
if ($request->post()) {
$request->validate([
'email' => 'required|email|unique:users,email,'.($o ? $o->id : NULL),
]);
foreach (['name','email','notes'] as $key)
$o->{$key} = $request->post($key);
$o->save();
return redirect()->action([self::class,'home']);
}
return view('user.addedit')
->with('o',$o);
}
public function home()
{
return view('user.home');
}
}

19
app/Models/System.php Normal file
View File

@ -0,0 +1,19 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use App\Traits\ScopeActive;
class System extends Model
{
use HasFactory,ScopeActive;
/* SCOPES */
/* RELATIONS */
/* CASTS */
}

View File

@ -0,0 +1,69 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateSystems extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('systems', function (Blueprint $table) {
$table->id();
$table->timestamps();
$table->string('name');
$table->string('sysop');
$table->string('location');
$table->text('notes');
$table->boolean('active');
$table->string('address')->nullable();
$table->integer('port')->nullable();
$table->integer('method')->nullable();
});
Schema::create('node_system', function (Blueprint $table) {
$table->integer('node_id');
$table->foreign('node_id')->references('id')->on('nodes');
$table->integer('system_id');
$table->foreign('system_id')->references('id')->on('systems');
});
Schema::create('system_user', function (Blueprint $table) {
$table->integer('user_id');
$table->foreign('user_id')->references('id')->on('users');
$table->integer('system_id');
$table->foreign('system_id')->references('id')->on('systems');
});
Schema::table('setups', function (Blueprint $table) {
$table->dropColumn('opt_md');
$table->integer('zmodem');
$table->integer('emsi_protocols');
$table->integer('binkp');
$table->integer('protocols');
$table->integer('permissions');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('setups', function (Blueprint $table) {
$table->integer('opt_md');
$table->dropColumn(['zmodem','emsi_protocols','binkp','protocols','permissions']);
});
Schema::dropIfExists('node_system');
Schema::dropIfExists('system_user');
Schema::dropIfExists('systems');
}
}

View File

@ -546,6 +546,9 @@ tbody {
border-bottom:1px solid #666; border-bottom:1px solid #666;
color: #eee; color: #eee;
} }
.monotable tbody tr.admin {
color: #ff3333;
}
.monotable tbody td { .monotable tbody td {
padding-left:1.5ch!important; padding-left:1.5ch!important;
padding-right:1.5ch!important; padding-right:1.5ch!important;

View File

@ -0,0 +1,46 @@
@extends('layouts.app')
@section('htmlheader_title')
Permissions for {{ auth()->check() ? auth()->user()->name : 'Guest' }}
@endsection
@section('content')
<h2>{{ auth()->check() ? auth()->user()->name : 'Guest' }}</h2>
<table class="table monotable">
<thead>
<tr>
<th>Test</th>
<th>Result</th>
</tr>
</thead>
<tbody>
<tr>
<td>isAdmin</td>
<td>@can('admin')YES @else NO @endcan</td>
</tr>
<tr>
<td>Domains</td>
<td>
<table class="table table-sm">
<thead>
<tr>
<th>Domain</th>
<th>Result</th>
</tr>
</thead>
<tbody>
@foreach (\App\Models\Domain::orderBy('name')->get() as $o)
<tr>
<td>{{ $o->name }}</td>
<td>@can('admin',$o)YES @else NO @endcan</td>
</tr>
@endforeach
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
@endsection

View File

@ -35,10 +35,10 @@
<label for="active" class="form-label">Active</label> <label for="active" class="form-label">Active</label>
<div class="input-group has-validation"> <div class="input-group has-validation">
<div class="btn-group" role="group"> <div class="btn-group" role="group">
<input type="radio" class="btn-check" name="active" id="active_yes" value="1" required @if($o->active)checked @endif> <input type="radio" class="btn-check" name="active" id="active_yes" value="1" required @if(old('active',$o->active))checked @endif>
<label class="btn btn-outline-success" for="active_yes">Yes</label> <label class="btn btn-outline-success" for="active_yes">Yes</label>
<input type="radio" class="btn-check btn-danger" name="active" id="active_no" value="0" required @if(! $o->active)checked @endif> <input type="radio" class="btn-check btn-danger" name="active" id="active_no" value="0" required @if(! old('active',$o->active))checked @endif>
<label class="btn btn-outline-danger" for="active_no">No</label> <label class="btn btn-outline-danger" for="active_no">No</label>
</div> </div>
</div> </div>
@ -47,7 +47,7 @@
<div class="row"> <div class="row">
<div class="col-4"> <div class="col-4">
<label for="name" class="form-label">DNS Domain</label> <label for="dnsdomain" class="form-label">DNS Domain</label>
<div class="input-group has-validation"> <div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-globe"></i></span> <span class="input-group-text"><i class="bi bi-globe"></i></span>
<input type="text" class="form-control @error('dnsdomain') is-invalid @enderror" id="dnsdomain" placeholder="DNS Domain (if applicable)" name="dnsdomain" value="{{ old('dnsdomain',$o->dnsdomain) }}"> <input type="text" class="form-control @error('dnsdomain') is-invalid @enderror" id="dnsdomain" placeholder="DNS Domain (if applicable)" name="dnsdomain" value="{{ old('dnsdomain',$o->dnsdomain) }}">
@ -63,17 +63,14 @@
<label for="public" class="form-label">Public</label> <label for="public" class="form-label">Public</label>
<div class="input-group has-validation"> <div class="input-group has-validation">
<div class="btn-group" role="group"> <div class="btn-group" role="group">
<input type="radio" class="btn-check" name="public" id="public_yes" value="1" required @if($o->public)checked @endif> <input type="radio" class="btn-check" name="public" id="public_yes" value="1" required @if(old('public',$o->public))checked @endif>
<label class="btn btn-outline-success" for="public_yes">Yes</label> <label class="btn btn-outline-success" for="public_yes">Yes</label>
<input type="radio" class="btn-check btn-danger" name="public" id="public_no" value="0" required @if(! $o->public)checked @endif> <input type="radio" class="btn-check btn-danger" name="public" id="public_no" value="0" required @if(! old('public',$o->public))checked @endif>
<label class="btn btn-outline-danger" for="public_no">No</label> <label class="btn btn-outline-danger" for="public_no">No</label>
</div> </div>
</div> </div>
</div> </div>
<div class="col-4">
more text
</div>
</div> </div>
<div class="row"> <div class="row">

View File

@ -6,7 +6,7 @@
@section('content') @section('content')
<div class="row"> <div class="row">
<div class="col-12"> <div class="col-12">
<h2>About the FTN Clearing House</h2> <h2>About FTN Domains</h2>
<p>In FTN network addresses, a domain is the 5th dimension and used when a system supports 5D addressing, ie: zone:hub/host@<strong class="highlight">domain</strong>.</p> <p>In FTN network addresses, a domain is the 5th dimension and used when a system supports 5D addressing, ie: zone:hub/host@<strong class="highlight">domain</strong>.</p>
<p>Domains are used with zones to uniquely identify a FTN network.</p> <p>Domains are used with zones to uniquely identify a FTN network.</p>
<p><small>Some legacy Fidonet software is not 5D aware and may behave unexpectedly when a domain is used</small></p> <p><small>Some legacy Fidonet software is not 5D aware and may behave unexpectedly when a domain is used</small></p>
@ -18,28 +18,34 @@
<p>This system is aware of the following domains:</p> <p>This system is aware of the following domains:</p>
@if (\App\Models\Domain::count() == 0) @if (\App\Models\Domain::count() == 0)
<p>There are no domains setup, to <a href="{{ url('ftn/domain/addedit') }}">set up your first</a>.</p> @can('admin',(new \App\Models\Domain))
<p>There are no domains setup, to <a href="{{ url('ftn/domain/addedit') }}">set up your first</a>.</p>
@else
<p class="pad">There are no domains - you need to ask an admin to create one for you.</p>
@endcan
@else @else
<table class="table monotable"> <table class="table monotable">
<thead> <thead>
<tr> <tr>
<th>ID</th> <th>ID</th>
<th>Active</th>
<th>Domain</th> <th>Domain</th>
<th>Active</th>
<th>DNS domain</th> <th>DNS domain</th>
<th>Zones</th> <th>Zones</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@can('admin',(new \App\Models\Domain()))
<tr> <tr>
<td colspan="5"><a href="{{ url('ftn/domain/addedit') }}">Add New Domain</a></td> <td colspan="5"><a href="{{ url('ftn/domain/addedit') }}">Add New Domain</a></td>
</tr> </tr>
@endcan
@foreach (\App\Models\Domain::orderBy('name')->cursor() as $oo) @foreach (\App\Models\Domain::orderBy('name')->cursor() as $oo)
<tr> <tr>
<td><a href="{{ url('ftn/domain/addedit',[$oo->id]) }}">{{ $oo->id }}</a></td> <td><a href="{{ url('ftn/domain/addedit',[$oo->id]) }}">{{ $oo->id }}</a></td>
<td>{{ $oo->active ? 'YES' : 'NO' }}</td>
<td>{{ $oo->name }}</td> <td>{{ $oo->name }}</td>
<td>{{ $oo->active ? 'YES' : 'NO' }}</td>
<td>{{ $oo->dnsdomain }}</td> <td>{{ $oo->dnsdomain }}</td>
<td>{{ join(', ',$oo->zones->pluck('zone_id')->toArray()) }}</td> <td>{{ join(', ',$oo->zones->pluck('zone_id')->toArray()) }}</td>
</tr> </tr>

View File

@ -0,0 +1,15 @@
@extends('layouts.auth')
@section('htmlheader_title')
403
@endsection
@section('content')
<div class="row">
<div class="col-6 m-auto">
<h3>403 - Not allowed</h3>
<p>Sorry, it appears you are not allowed to do that.</p>
<p><a href="{{ url('/') }}" class="goback">Home</a></p>
</div>
</div>
@endsection

View File

@ -4,6 +4,7 @@
<dl> <dl>
<dt>Network Admin</dt> <dt>Network Admin</dt>
<dd><a href="{{ url('ftn/domain') }}">Domains</a></dd> <dd><a href="{{ url('ftn/domain') }}">Domains</a></dd>
<dd><a href="{{ url('ftn/system') }}">Systems</a></dd>
<dd><a href="{{ url('ftn/zone') }}" >Zones</a></dd> <dd><a href="{{ url('ftn/zone') }}" >Zones</a></dd>
<dd><a href="{{ url('ftn/node') }}" >Nodes</a></dd> <dd><a href="{{ url('ftn/node') }}" >Nodes</a></dd>
</dl> </dl>

View File

@ -0,0 +1,8 @@
@extends('layouts.app')
@section('htmlheader_title')
Setup
@endsection
@section('content')
<h2>Site Setup</h2>
@endsection

View File

@ -0,0 +1,76 @@
@extends('layouts.app')
@section('htmlheader_title')
Systems
@endsection
@section('content')
<div class="row">
<div class="col-12">
<h2>BBS Systems</h2>
<p>BBS Systems Send and Receive Echomail and Files.</p>
</div>
</div>
<div class="row">
<div class="col-6">
<p>This system is aware of the following systems:</p>
@if (\App\Models\System::count() == 0)
@can('admin',(new \App\Models\System))
<p>There are no systems setup, to <a href="{{ url('ftn/system/addedit') }}">set up your first</a>.</p>
@else
<p class="pad">There are no systems - you need to ask an admin to create one for you.</p>
@endcan
@else
<table class="table monotable">
<thead>
<tr>
<th>ID</th>
<th>System</th>
<th>Sysop</th>
<th>Location</th>
<th>Active</th>
<th>Connect</th>
</tr>
</thead>
<tbody>
@can('admin',(new \App\Models\System))
<tr>
<td colspan="6"><a href="{{ url('ftn/domain/addedit') }}">Add New System</a></td>
</tr>
@endcan
@foreach (\App\Models\System::orderBy('name')->cursor() as $oo)
<tr>
<td><a href="{{ url('ftn/system/addedit',[$oo->id]) }}">{{ $oo->id }}</a></td>
<td>{{ $oo->name }}</td>
<td>{{ $oo->sysop }}</td>
<td>{{ $oo->location }}</td>
<td>{{ $oo->active ? 'YES' : 'NO' }}</td>
<td>
@switch($oo->method)
@case(23)<a href="telnet://{{ $oo->address }}:{{ $oo->port }}">Telnet</a>@break
@case(22)<a href="ssh://{{ $oo->address }}:{{ $oo->port }}">SSH</a>@break
@case(519)<a href="rlogin://{{ $oo->address }}:{{ $oo->port }}">SSH</a>@break
@default No details
@endswitch
</td>
</tr>
@endforeach
</tbody>
</table>
@endif
</div>
</div>
@endsection
@section('page-scripts')
<script type="text/javascript">
$('table tr').click(function() {
var href = $(this).find('a').attr('href');
if (href)
window.location = href;
});
</script>
@append

View File

@ -0,0 +1,51 @@
@extends('layouts.app')
@section('htmlheader_title')
Users
@endsection
@section('content')
<div class="row">
<div class="col-8">
<p>Current Users:</p>
<table class="table monotable">
<thead>
<tr>
<th>ID</th>
<th>Email</th>
<th>Name</th>
<th>Verified</th>
<th>Last On</th>
</tr>
</thead>
<tbody>
@can('admin',(new \App\Models\Domain()))
<tr>
<td colspan="5"><a href="{{ url('user/addedit') }}">Add New User</a></td>
</tr>
@endcan
@foreach (\App\Models\User::orderBy('email')->cursor() as $oo)
<tr class="{{ $oo->admin ? 'admin' : '' }}">
<td><a href="{{ url('user/addedit',[$oo->id]) }}">{{ $oo->id }}</a></td>
<td>{{ $oo->email }}</td>
<td>{{ $oo->name }}</td>
<td>{{ $oo->email_verified_at ? $oo->email_verified_at->format('Y-m-d') : '-' }}</td>
<td>{{-- $oo->last_on --}}TBA</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
@endsection
@section('page-scripts')
<script type="text/javascript">
$('table tr').click(function() {
var href = $(this).find('a').attr('href');
if (href)
window.location = href;
});
</script>
@append

View File

@ -3,7 +3,7 @@
use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Route; use Illuminate\Support\Facades\Route;
use App\Http\Controllers\{HomeController,DomainController,NodeController,ZoneController}; use App\Http\Controllers\{HomeController,DomainController,NodeController,SystemController,UserController,ZoneController};
use App\Http\Controllers\Auth\LoginController; use App\Http\Controllers\Auth\LoginController;
/* /*
@ -39,13 +39,20 @@ Route::middleware(['verified'])->group(function () {
Route::match(['get','post'],'ftn/node/addedit/{o?}',[NodeController::class,'add_edit']) Route::match(['get','post'],'ftn/node/addedit/{o?}',[NodeController::class,'add_edit'])
->where('o','[0-9]+'); ->where('o','[0-9]+');
Route::get('ftn/system',[SystemController::class,'home']);
Route::match(['get','post'],'ftn/system/addedit/{o?}',[SystemController::class,'add_edit'])
->where('o','[0-9]+');
Route::get('ftn/zone',[ZoneController::class,'home']); Route::get('ftn/zone',[ZoneController::class,'home']);
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('network/{o}',[HomeController::class,'network']); Route::get('network/{o}',[HomeController::class,'network']);
Route::get('permissions',[HomeController::class,'permissions']);
Route::middleware(['auth','can:admin'])->group(function () { Route::middleware(['auth','can:admin'])->group(function () {
Route::get('setup',[HomeController::class,'setup']); Route::get('setup',[HomeController::class,'setup']);
Route::get('user/list',[UserController::class,'home']);
}); });