Compare commits

..

No commits in common. "6a41536d5761729d9a52f2363ee044d237752fe1" and "001618d719dd92e309cc81bd676f036ca16d9bd7" have entirely different histories.

58 changed files with 1583 additions and 1973 deletions

View File

@ -2,14 +2,13 @@
namespace App\Http\Controllers\Auth; namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
use Carbon\Carbon; use Carbon\Carbon;
use Illuminate\Foundation\Auth\AuthenticatesUsers; use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Auth;
use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
class LoginController extends Controller class LoginController extends Controller
{ {
/* /*
@ -39,8 +38,7 @@ class LoginController extends Controller
*/ */
public function __construct() public function __construct()
{ {
$this->middleware('guest') $this->middleware('guest')->except('logout');
->except('logout');
} }
public function login(Request $request) public function login(Request $request)
@ -72,7 +70,6 @@ class LoginController extends Controller
if (file_exists('login_note.txt')) if (file_exists('login_note.txt'))
$login_note = file_get_contents('login_note.txt'); $login_note = file_get_contents('login_note.txt');
return view('auth.login') return view('auth.login')->with('login_note',$login_note);
->with('login_note',$login_note);
} }
} }

View File

@ -39,7 +39,7 @@ class HomeController extends Controller
}) })
->get(); ->get();
return view('widgets.file') return view('file')
->with('f',$f); ->with('f',$f);
} }
@ -73,11 +73,20 @@ class HomeController extends Controller
->with(['echoarea']) ->with(['echoarea'])
->get(); ->get();
return view('widgets.packet') return view('packet')
->with('nm',$nm) ->with('nm',$nm)
->with('em',$em); ->with('em',$em);
} }
/**
* Render a view that summarises the users permissions
*/
public function permissions()
{
return view('auth.permissions')
->with('user',Auth::user());
}
/** /**
* Show a packet dump * Show a packet dump
* *

View File

@ -323,7 +323,7 @@ class SystemController extends Controller
// Make sure that no other system has this address active. // Make sure that no other system has this address active.
if ($o->role === Address::NODE_ACTIVE) if ($o->role === Address::NODE_ACTIVE)
return redirect()->back()->withErrors(['address'=>sprintf('%s cannot be demoted any more',$o->ftn3D)]); return redirect()->back()->withErrors(['demaddress'=>sprintf('%s cannot be demoted any more',$o->ftn3D)]);
$o->role = ($o->role << 1); $o->role = ($o->role << 1);
$o->save(); $o->save();
@ -494,7 +494,7 @@ class SystemController extends Controller
// Make sure that no other system has this address active. // Make sure that no other system has this address active.
if ($o->role === Address::NODE_NC) if ($o->role === Address::NODE_NC)
return redirect()->back()->withErrors(['address'=>sprintf('%s cannot be promoted any more',$o->ftn3D)]); return redirect()->back()->withErrors(['proaddress'=>sprintf('%s cannot be promoted any more',$o->ftn3D)]);
$o->role = ($o->role >> 1); $o->role = ($o->role >> 1);
$o->save(); $o->save();
@ -564,7 +564,7 @@ class SystemController extends Controller
'active'=>TRUE, 'active'=>TRUE,
])->single())) { ])->single())) {
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)]); return redirect()->back()->withErrors(['susaddress'=>sprintf('%s is already active on system [<a href="%s">%s</a>]',$o->ftn,url('system/addedit',$x->system_id),$x->system->name)]);
} }
$o->active = (! $o->active); $o->active = (! $o->active);

View File

@ -5,7 +5,6 @@ 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\Hash;
use Illuminate\Support\Facades\Validator; use Illuminate\Support\Facades\Validator;
use App\Http\Requests\UserRequest; use App\Http\Requests\UserRequest;
@ -24,17 +23,13 @@ class UserController extends Controller
if (! $o->exists) if (! $o->exists)
$o->password = base64_encode(random_bytes(20)); $o->password = base64_encode(random_bytes(20));
elseif ($request->password)
$o->password = Hash::make($request->password);
$o->save(); $o->save();
if ($o->wasRecentlyCreated) if ($o->wasRecentlyCreated)
event(new Registered($o)); event(new Registered($o));
return redirect() return redirect()->to('user');
->to('user/addedit/'.$o->id)
->with('success','User Updated');
} }
return view('user.addedit') return view('user.addedit')
@ -70,4 +65,9 @@ class UserController extends Controller
return view('user.link'); return view('user.link');
} }
public function register()
{
return view('user/system/register');
}
} }

View File

@ -14,7 +14,7 @@ class AddressMerge extends FormRequest
public function authorize() public function authorize()
{ {
return Gate::allows('admin'); return Gate::allows( 'admin');
} }
public function rules(Request $request) public function rules(Request $request)

View File

@ -12,7 +12,7 @@ class AreafixRequest extends FormRequest
{ {
public function authorize() public function authorize()
{ {
return Gate::allows('admin'); return Gate::allows( 'admin');
} }
public function rules(Request $request) public function rules(Request $request)

View File

@ -12,7 +12,7 @@ class DomainRequest extends FormRequest
{ {
public function authorize(Domain $o) public function authorize(Domain $o)
{ {
return Gate::allows('admin',$o); return Gate::allows( 'admin',$o);
} }
public function rules(Request $request) public function rules(Request $request)

View File

@ -10,7 +10,7 @@ class SetupRequest extends FormRequest
{ {
public function authorize() public function authorize()
{ {
return Gate::allows('admin'); return Gate::allows( 'admin');
} }
public function rules(Request $request) public function rules(Request $request)

View File

@ -7,11 +7,13 @@ use Illuminate\Http\Request;
use Illuminate\Support\Facades\Gate; use Illuminate\Support\Facades\Gate;
use Illuminate\Validation\Rule; use Illuminate\Validation\Rule;
use App\Models\User;
class UserRequest extends FormRequest class UserRequest extends FormRequest
{ {
public function authorize() public function authorize()
{ {
return Gate::any(['admin','update'],$this->route('o')); return Gate::allows( 'admin');
} }
public function rules(Request $request) public function rules(Request $request)

View File

@ -57,8 +57,7 @@ class User extends Authenticatable implements MustVerifyEmail
*/ */
protected $casts = [ protected $casts = [
'email_verified_at' => 'datetime', 'email_verified_at' => 'datetime',
'last_on' => 'datetime:Y-m-d H:i:s', 'last_on' => 'datetime:Y-m-d H:i:s'
'passkey' => 'json',
]; ];
/* RELATIONS */ /* RELATIONS */

View File

@ -18,7 +18,6 @@
"laravel/sanctum": "^3.2", "laravel/sanctum": "^3.2",
"laravel/ui": "^4.0", "laravel/ui": "^4.0",
"league/flysystem-aws-s3-v3": "^3.0", "league/flysystem-aws-s3-v3": "^3.0",
"leenooks/passkey": "^0.1.0",
"nunomaduro/laravel-console-summary": "^1.9", "nunomaduro/laravel-console-summary": "^1.9",
"rennokki/laravel-eloquent-query-cache": "^3.3", "rennokki/laravel-eloquent-query-cache": "^3.3",
"repat/laravel-job-models": "^0.8", "repat/laravel-job-models": "^0.8",
@ -48,10 +47,6 @@
} }
}, },
"repositories": { "repositories": {
"passkey": {
"type": "vcs",
"url": "https://gitea.dege.au/laravel/passkey.git"
},
"laravel-console-summary": { "laravel-console-summary": {
"type": "vcs", "type": "vcs",
"url": "https://github.com/leenooks/laravel-console-summary" "url": "https://github.com/leenooks/laravel-console-summary"

88
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "0f0e0e75d37ebcbcbc03996fb1f3e18b", "content-hash": "b9697fb5a34c3ed05cea0ce107b63d3f",
"packages": [ "packages": [
{ {
"name": "aglipanci/laravel-eloquent-case", "name": "aglipanci/laravel-eloquent-case",
@ -1700,51 +1700,6 @@
}, },
"time": "2023-05-09T19:47:28+00:00" "time": "2023-05-09T19:47:28+00:00"
}, },
{
"name": "lbuchs/webauthn",
"version": "v2.1.1",
"source": {
"type": "git",
"url": "https://github.com/lbuchs/WebAuthn.git",
"reference": "e73ff007e8a1099e72e0dbdd9d0884057409fc54"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/lbuchs/WebAuthn/zipball/e73ff007e8a1099e72e0dbdd9d0884057409fc54",
"reference": "e73ff007e8a1099e72e0dbdd9d0884057409fc54",
"shasum": ""
},
"require": {
"php": ">=8.0.0"
},
"type": "library",
"autoload": {
"psr-4": {
"lbuchs\\WebAuthn\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Lukas Buchs",
"role": "Developer"
}
],
"description": "A simple PHP WebAuthn (FIDO2) server library",
"homepage": "https://github.com/lbuchs/webauthn",
"keywords": [
"Authentication",
"webauthn"
],
"support": {
"issues": "https://github.com/lbuchs/WebAuthn/issues",
"source": "https://github.com/lbuchs/WebAuthn/tree/v2.1.1"
},
"time": "2024-01-15T15:46:57+00:00"
},
{ {
"name": "league/commonmark", "name": "league/commonmark",
"version": "2.4.1", "version": "2.4.1",
@ -2205,47 +2160,6 @@
], ],
"time": "2023-10-17T14:13:20+00:00" "time": "2023-10-17T14:13:20+00:00"
}, },
{
"name": "leenooks/passkey",
"version": "0.1.0",
"source": {
"type": "git",
"url": "https://gitea.dege.au/laravel/passkey.git",
"reference": "4872d55ed65863e03102eea1046504e630f80ae2"
},
"require": {
"lbuchs/webauthn": "^2.1"
},
"type": "library",
"extra": {
"laravel": {
"providers": [
"Leenooks\\Passkey\\PasskeyServiceProvider"
]
}
},
"autoload": {
"psr-4": {
"Leenooks\\Passkey\\": "src"
}
},
"license": [
"MIT"
],
"authors": [
{
"name": "Deon George",
"email": "deon@dege.au"
}
],
"description": "Leenooks Laravel Passkey Implementation",
"keywords": [
"dege",
"laravel",
"passkey"
],
"time": "2024-04-25T05:05:51+00:00"
},
{ {
"name": "masterminds/html5", "name": "masterminds/html5",
"version": "2.8.1", "version": "2.8.1",

35
public/css/fixes.css vendored
View File

@ -99,38 +99,3 @@ ol {
color: inherit; color: inherit;
background-color: inherit; background-color: inherit;
} }
/* h1 headings reference */
h1>small.float-end {
padding-top: 2rem;
}
h1>small.float-end:before {
color: #acacac;
content: '[';
}
h1>small.float-end:after {
color: #acacac;
content: ']';
}
h1 sup {
text-shadow: none;
font-size: 50%;
top: -1em;
}
h1>small.success {
color: #005300 !important;
}
h1>small.success:before {
color: #00aa00;
content: '[';
}
h1>small.success:after {
color: #00aa00;
content: ']';
}
/* Ensure our greyframe titled boxes are full width */
.titledbox {
margin-right: 0;
margin-left: 0;
}

View File

@ -1,225 +0,0 @@
/*
* Passkey Implementation
*/
let passkey_debug = false;
/**
* Convert a ArrayBuffer to Base64
* @param {ArrayBuffer} buffer
* @returns {String}
*/
function arrayBufferToBase64(buffer) {
let binary = '';
let bytes = new Uint8Array(buffer);
let len = bytes.byteLength;
for (let i = 0; i < len; i++) {
binary += String.fromCharCode( bytes[ i ] );
}
return window.btoa(binary);
}
/**
* convert RFC 1342-like base64 strings to array buffer
* @param {mixed} obj
* @returns {undefined}
*/
function recursiveBase64StrToArrayBuffer(obj) {
let prefix = '=?BINARY?B?';
let suffix = '?=';
if (typeof obj === 'object') {
for (let key in obj) {
if (typeof obj[key] === 'string') {
let str = obj[key];
if (str.substring(0, prefix.length) === prefix && str.substring(str.length - suffix.length) === suffix) {
str = str.substring(prefix.length, str.length - suffix.length);
let binary_string = window.atob(str);
let len = binary_string.length;
let bytes = new Uint8Array(len);
for (let i = 0; i < len; i++) {
bytes[i] = binary_string.charCodeAt(i);
}
obj[key] = bytes.buffer;
}
} else {
recursiveBase64StrToArrayBuffer(obj[key]);
}
}
}
}
function passkey_check_browser()
{
// check browser support
if ((! window.fetch) || (! navigator.credentials) || (! navigator.credentials.create))
throw new Error('Browser not supported.');
/*
// Availability of `window.PublicKeyCredential` means WebAuthn is usable.
// `isUserVerifyingPlatformAuthenticatorAvailable` means the feature detection is usable.
// `isConditionalMediationAvailable` means the feature detection is usable.
if (window.PublicKeyCredential &&
PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable &&
PublicKeyCredential.isConditionalMediationAvailable) {
// Check if user verifying platform authenticator is available.
Promise.all([
PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable(),
PublicKeyCredential.isConditionalMediationAvailable(),
]).then(results => {
if (results.every(r => r === true)) {
// Display "Create a new passkey" button
}
});
}
*/
if (passkey_debug)
console.log('Passkey: Browser OK');
return true;
}
/**
* Register/Create a passkey for a user
*/
async function passkey_register(csrf_token,icon_dom,icon,icon_shell_success,icon_shell_fail)
{
try {
if (! passkey_check_browser())
return;
// Change our icon so that it is obvious we are doing something
icon_dom.find('i').removeClass(icon).addClass('spinner-grow spinner-grow-sm');
// Get our arguments
var createArgs;
$.ajax({
url: '/passkey/register',
type: 'GET',
dataType: 'json',
async: false,
cache: false,
success: function(data) {
if (passkey_debug)
console.log('Passkey: Get Register Success');
recursiveBase64StrToArrayBuffer(data);
createArgs = data;
},
error: function(e,status,error) {
throw new Error(status || 'Unknown error occurred');
}
});
// Create credentials
try {
const cred = await navigator.credentials.create(createArgs);
const authenticatorAttestationResponse = {
id: cred.id,
rawId: arrayBufferToBase64(cred.rawId),
transports: cred.response.getTransports ? cred.response.getTransports() : null,
clientDataJSON: cred.response.clientDataJSON ? arrayBufferToBase64(cred.response.clientDataJSON) : null,
attestationObject: cred.response.attestationObject ? arrayBufferToBase64(cred.response.attestationObject) : null,
authenticatorAttachment: cred.authenticatorAttachment,
_token: csrf_token,
};
$.ajax({
url: '/passkey/check',
type: 'POST',
data: authenticatorAttestationResponse,
cache: false,
success: function(data) {
if (passkey_debug)
console.log('Passkey: Registration Success');
icon_dom.find('i').addClass(icon).removeClass('spinner-grow spinner-grow-sm');
icon_dom.removeClass('btn-outline-primary').addClass('btn-primary');
},
error: function(e,status,error) {
throw new Error(status || 'Unknown error occurred');
}
});
} catch (status) {
if (passkey_debug)
console.log(status || 'Passkey: User Aborted Register');
// Restore the icon
icon_dom.find('i').addClass(icon).removeClass('spinner-grow spinner-grow-sm');
return;
}
} catch (err) {
window.alert(err || 'An UNKNOWN error occurred?');
}
}
/**
* Check a passkey being presented
*/
async function passkey_check(csrf_token,redirect)
{
if (passkey_debug)
console.log('Passkey: Check User Passkey');
try {
if (! passkey_check_browser())
return;
// Get our arguments
var getArgs;
$.ajax({
url: '/passkey/get',
type: 'GET',
dataType: 'json',
async: false,
cache: false,
success: function(data) {
if (passkey_debug)
console.log('Passkey: Get Args Success');
recursiveBase64StrToArrayBuffer(data);
getArgs = data;
},
error: function(e,status,error) {
throw new Error(status || 'Unknown error occurred');
}
});
// check credentials with hardware
const cred = await navigator.credentials.get(getArgs);
// create object for transmission to server
const authenticatorAttestationResponse = {
id: cred.rawId ? arrayBufferToBase64(cred.rawId) : null,
clientDataJSON: cred.response.clientDataJSON ? arrayBufferToBase64(cred.response.clientDataJSON) : null,
authenticatorData: cred.response.authenticatorData ? arrayBufferToBase64(cred.response.authenticatorData) : null,
signature: cred.response.signature ? arrayBufferToBase64(cred.response.signature) : null,
userHandle: cred.response.userHandle ? arrayBufferToBase64(cred.response.userHandle) : null,
_token: csrf_token
};
$.ajax({
url: '/passkey/process',
type: 'POST',
data: authenticatorAttestationResponse,
cache: false,
success: function(data) {
if (passkey_debug)
console.log('Passkey: Process Success');
// Direct to the home page
window.location.href = (redirect !== undefined) ? redirect : '/';
},
error: function(e,status,error) {
throw new Error(status || 'Unknown error occurred');
}
});
} catch (err) {
window.alert(err || 'An UNKNOWN error occurred?');
}
}

View File

@ -5,7 +5,7 @@
@endsection @endsection
@section('content') @section('content')
@if(isset($login_note) && $login_note) @if(isset($login_note) AND $login_note)
<div class="row"> <div class="row">
<div class="col-8 m-auto"> <div class="col-8 m-auto">
<div class="alert alert-info alert-dismissible" role="alert"> <div class="alert alert-info alert-dismissible" role="alert">
@ -20,21 +20,20 @@
</div> </div>
@endisset @endisset
<form class="needs-validation" method="post" novalidate> <div class="row">
@csrf <div class="col-6 m-auto">
<div class="greyframe titledbox shadow0xb0 text-center">
<h2 class="cap">Login</h2>
<div class="row"> <form class="row g-0 needs-validation" method="post" novalidate>
<div class="col-6 m-auto"> @csrf
<div class="greyframe titledbox shadow0xb0 text-center">
<h2 class="cap">Login</h2>
<div class="row"> <div class="row">
<div class="col-12"> <div class="col-12">
<label for="email" class="form-label">Email</label> <label for="email" class="form-label">Email</label>
<div class="input-group has-validation"> <div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-person-badge"></i></span> <span class="input-group-text"><i class="bi bi-person-badge"></i></span>
<!-- Conditionally display passkeys in autofill --> <input type="text" class="form-control @error('email') is-invalid @enderror" id="email" placeholder="Email" name="email" required autocomplete="email" autofocus>
<input type="text" class="form-control @error('email') is-invalid @enderror" id="email" placeholder="Email" name="email" required autocomplete="email webauthn" autofocus>
<span class="invalid-feedback" role="alert"> <span class="invalid-feedback" role="alert">
@error('email') @error('email')
{{ $message }} {{ $message }}
@ -51,7 +50,7 @@
<label for="password" class="form-label">Password</label> <label for="password" class="form-label">Password</label>
<div class="input-group has-validation"> <div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-key-fill"></i></span> <span class="input-group-text"><i class="bi bi-key-fill"></i></span>
<input type="password" class="form-control" id="password" placeholder="Password" name="password" autocomplete="new-password" required> <input type="password" class="form-control" id="password" placeholder="Password" name="password" required>
<span class="invalid-feedback" role="alert"> <span class="invalid-feedback" role="alert">
Your password is required. Your password is required.
</span> </span>
@ -71,29 +70,20 @@
<button type="submit" name="submit" class="btn btn-success float-end">Sign In</button> <button type="submit" name="submit" class="btn btn-success float-end">Sign In</button>
</div> </div>
</div> </div>
</form>
<div class="row"> <div class="row">
<div class="col-12"> <div class="col-12">
<a class="link-danger" href="{{ url('password/reset') }}">Forgot Password</a> <a class="link-danger" href="{{ url('password/reset') }}">Forgot Password</a>
</div>
</div> </div>
</div>
<div class="row"> <div class="row">
<div class="col-12"> <div class="col-12">
<a class="link-danger" href="{{ url('register') }}">Register</a> <a class="link-danger" href="{{ url('register') }}">Register</a>
</div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</form> </div>
@endsection @endsection
@section('page-scripts')
<!-- Passkeys -->
<script type='text/javascript' src='{{ asset('/passkey/passkey.js') }}'></script>
<script type="text/javascript">
passkey_check('{{ csrf_token() }}','{{ back()->getTargetUrl() }}');
</script>
@append

View File

@ -5,15 +5,23 @@
@endsection @endsection
@section('content') @section('content')
@includeWhen(session()->has('success'),'widgets.success-row',['msg'=>session()->get('success')]) @if (Session('status'))
<form class="needs-validation" method="post" action="{{ route('password.email') }}" novalidate>
@csrf
<div class="row"> <div class="row">
<div class="col-6 m-auto"> <div class="col-8 m-auto">
<div class="greyframe titledbox shadow0xb0 text-center"> <div class="alert alert-success" role="alert">
<h2 class="cap">Forgot Password</h2> {{ session('status') }}
</div>
</div>
</div>
@endif
<div class="row">
<div class="col-6 m-auto">
<div class="greyframe titledbox shadow0xb0 text-center">
<h2 class="cap">Forgot Password</h2>
<form class="row g-0 needs-validation" method="post" action="{{ route('password.email') }}" novalidate>
@csrf
<div class="row"> <div class="row">
<div class="col-12"> <div class="col-12">
@ -44,8 +52,8 @@
<a class="link-danger" href="{{ url('login') }}">Login</a> <a class="link-danger" href="{{ url('login') }}">Login</a>
</div> </div>
</div> </div>
</div> </form>
</div> </div>
</div> </div>
</form> </div>
@endsection @endsection

View File

@ -5,16 +5,23 @@
@endsection @endsection
@section('content') @section('content')
@includeWhen(session()->has('status') || true,'widgets.success-row',['msg'=>session()->get('status')]) @if (Session('status'))
<form class="needs-validation" method="post" action="{{ route('password.update') }}" novalidate>
@csrf
<div class="row"> <div class="row">
<div class="col-6 m-auto"> <div class="col-8 m-auto">
<div class="greyframe titledbox shadow0xb0 text-center"> <div class="alert alert-success" role="alert">
<h2 class="cap">Reset Password</h2> {{ session('status') }}
</div>
</div>
</div>
@endif
<div class="row">
<div class="col-6 m-auto">
<div class="greyframe titledbox shadow0xb0 text-center">
<h2 class="cap">Reset Password</h2>
<form class="row g-0 needs-validation" method="post" action="{{ route('password.update') }}" novalidate>
@csrf
<input type="hidden" name="token" value="{{ $token }}"> <input type="hidden" name="token" value="{{ $token }}">
<div class="row"> <div class="row">
@ -70,8 +77,8 @@
<button type="submit" name="submit" class="btn btn-success float-end">Sign In</button> <button type="submit" name="submit" class="btn btn-success float-end">Sign In</button>
</div> </div>
</div> </div>
</div> </form>
</div> </div>
</div> </div>
</form> </div>
@endsection @endsection

View File

@ -4,95 +4,91 @@
@endsection @endsection
@section('content') @section('content')
<div class="row"> <h2>{{ auth()->check() ? auth()->user()->name : 'Guest' }}</h2>
<div class="col-12">
<h2>{{ auth()->check() ? auth()->user()->name : 'Guest' }}</h2>
<table class="table monotable"> <table class="table monotable">
<thead> <thead>
<tr> <tr>
<th>Test</th> <th>Test</th>
<th>Result</th> <th>Result</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr> <tr>
<td>isAdmin</td> <td>isAdmin</td>
<td>@can('admin')YES @else NO @endcan</td> <td>@can('admin')YES @else NO @endcan</td>
</tr> </tr>
<tr> <tr>
<td>Domains</td> <td>Domains</td>
<td> <td>
<table class="table table-sm" id="domains"> <table class="table table-sm" id="domains">
<thead> <thead>
<tr> <tr>
<th class="w-75">Domain</th> <th class="w-75">Domain</th>
<th>Result</th> <th>Result</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@foreach (\App\Models\Domain::orderBy('name')->get() as $o) @foreach (\App\Models\Domain::orderBy('name')->get() as $o)
<tr> <tr>
<td>{{ $o->name }}</td> <td>{{ $o->name }}</td>
<td>@can('admin',$o)YES @else NO @endcan</td> <td>@can('admin',$o)YES @else NO @endcan</td>
</tr> </tr>
@endforeach @endforeach
</tbody> </tbody>
</table> </table>
</td> </td>
</tr> </tr>
<tr> <tr>
<td>System</td> <td>System</td>
<td> <td>
<table class="table table-sm" id="systems"> <table class="table table-sm" id="systems">
<thead> <thead>
<tr> <tr>
<th class="w-75">System</th> <th class="w-75">System</th>
<th>Result</th> <th>Result</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@foreach (\App\Models\System::orderBy('name')->with(['users'])->get() as $o) @foreach (\App\Models\System::orderBy('name')->with(['users'])->get() as $o)
<tr> <tr>
<td>{{ $o->name }}</td> <td>{{ $o->name }}</td>
<td>@can('update',$o)YES @else NO @endcan</td> <td>@can('update',$o)YES @else NO @endcan</td>
</tr> </tr>
@endforeach @endforeach
</tbody> </tbody>
</table> </table>
</td> </td>
</tr> </tr>
<tr> <tr>
<td>Zone</td> <td>Zone</td>
<td> <td>
<table class="table table-sm" id="zones"> <table class="table table-sm" id="zones">
<thead> <thead>
<tr> <tr>
<th class="w-75">Zone</th> <th class="w-75">Zone</th>
<th>Result</th> <th>Result</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@foreach (\App\Models\Zone::orderBy('zone_id')->get() as $o) @foreach (\App\Models\Zone::orderBy('zone_id')->get() as $o)
<tr> <tr>
<td>{{ $o->zone_id }}</td> <td>{{ $o->zone_id }}</td>
<td>@can('admin',$o)YES @else NO @endcan</td> <td>@can('admin',$o)YES @else NO @endcan</td>
</tr> </tr>
@endforeach @endforeach
</tbody> </tbody>
</table> </table>
</td> </td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
</div>
</div>
@endsection @endsection
@section('page-css') @section('page-css')

View File

@ -5,13 +5,13 @@
@endsection @endsection
@section('content') @section('content')
<form class="needs-validation" method="post" novalidate> <div class="row">
@csrf <div class="col-6 m-auto">
<div class="greyframe titledbox shadow0xb0 text-center">
<h2 class="cap">Register</h2>
<div class="row"> <form class="row g-0 needs-validation" method="post" novalidate>
<div class="col-6 m-auto"> @csrf
<div class="greyframe titledbox shadow0xb0 text-center">
<h2 class="cap">Register</h2>
<div class="row"> <div class="row">
<div class="col-12"> <div class="col-12">
@ -82,14 +82,14 @@
<button type="submit" name="submit" class="btn btn-success float-end">Sign In</button> <button type="submit" name="submit" class="btn btn-success float-end">Sign In</button>
</div> </div>
</div> </div>
</form>
<div class="row"> <div class="row">
<div class="col-12"> <div class="col-12">
<a class="link-danger" href="{{ url('login') }}">Login</a> <a class="link-danger" href="{{ url('login') }}">Login</a>
</div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</form> </div>
@endsection @endsection

View File

@ -5,13 +5,23 @@
@endsection @endsection
@section('content') @section('content')
<form class="needs-validation" method="post" action="{{ route('verification.resend') }}" novalidate> @if (Session('resent'))
@csrf
<div class="row"> <div class="row">
<div class="col-6 m-auto"> <div class="col-8 m-auto">
<div class="greyframe titledbox shadow0xb0 text-center"> <div class="alert alert-success alert-dismissible" role="alert">
<h2 class="cap">Verify</h2> {{ __('A fresh verification link has been sent to your email address.') }}
</div>
</div>
</div>
@endif
<div class="row">
<div class="col-6 m-auto">
<div class="greyframe titledbox shadow0xb0 text-center">
<h2 class="cap">Verify</h2>
<form class="row" method="post" action="{{ route('verification.resend') }}" novalidate>
@csrf
<div class="row"> <div class="row">
<div class="col-12"> <div class="col-12">
@ -20,8 +30,8 @@
<button type="submit" class="btn btn-link p-0" style="text-decoration: none;line-height: 1.0;">{{ __('click here to request another') }}</button>. <button type="submit" class="btn btn-link p-0" style="text-decoration: none;line-height: 1.0;">{{ __('click here to request another') }}</button>.
</div> </div>
</div> </div>
</div> </form>
</div> </div>
</div> </div>
</form> </div>
@endsection @endsection

View File

@ -5,7 +5,7 @@
@endsection @endsection
@section('content') @section('content')
<form class="needs-validation" method="post" novalidate> <form class="row g-0 needs-validation" method="post" novalidate>
@csrf @csrf
<div class="row"> <div class="row">

View File

@ -4,12 +4,14 @@
@endsection @endsection
@section('content') @section('content')
<div class="row"> <div class="row pt-0">
<div class="col-12"> <div class="col-12">
<h2>List of known FTN Networks</h2> <h2>List of known FTN Networks</h2>
<p>Here is a list of known <strong class="highlight">FTN Networks</strong>.</p> <p>Here is a list of known <strong class="highlight">FTN Networks</strong>.</p>
</div>
<div class="col-12 pt-2">
<table class="table monotable" id="ftnlist"> <table class="table monotable" id="ftnlist">
<thead> <thead>
<tr> <tr>

View File

@ -5,174 +5,170 @@
@endsection @endsection
@section('content') @section('content')
<div class="row"> <h1>{{ $o->name }} <small class="float-end pt-4">Last Update: {{ $o->updated_at->format('Y-m-d H:i') }}</small></h1>
<div class="col-12">
<h1>{{ $o->name }} <small class="float-end">Last Update: {{ $o->updated_at->format('Y-m-d H:i') }}</small></h1>
<div class="accordion" id="accordion_homepage"> <div class="accordion" id="accordion_homepage">
<!-- About --> <!-- About -->
<div class="accordion-item"> <div class="accordion-item">
<h3 class="accordion-header"> <h3 class="accordion-header">
<span class="accordion-button" id="about" data-bs-toggle="collapse" data-bs-target="#collapse_about" aria-expanded="true" aria-controls="collapse_about">About</span> <span class="accordion-button" id="about" data-bs-toggle="collapse" data-bs-target="#collapse_about" aria-expanded="true" aria-controls="collapse_about">About</span>
</h3> </h3>
<div id="collapse_about" class="accordion-collapse collapse show" aria-labelledby="about" data-bs-parent="#accordion_homepage"> <div id="collapse_about" class="accordion-collapse collapse show" aria-labelledby="about" data-bs-parent="#accordion_homepage">
<div class="accordion-body"> <div class="accordion-body">
<div class="float-end" style="max-height: 25em;" id="network_traffic"></div> <div class="float-end" style="max-height: 25em;" id="network_traffic"></div>
{!! \Illuminate\Mail\Markdown::parse($o->homepage) !!} {!! \Illuminate\Mail\Markdown::parse($o->homepage) !!}
</div>
</div>
</div> </div>
</div>
</div>
<!-- Echomail --> <!-- Echomail -->
<div class="accordion-item"> <div class="accordion-item open">
<h3 class="accordion-header"> <h3 class="accordion-header">
<span class="accordion-button collapsed" id="echoareas" data-bs-toggle="collapse" data-bs-target="#collapse_echoareas" aria-expanded="false" aria-controls="collapse_echoareas">Echo Areas</span> <span class="accordion-button collapsed" id="echoareas" data-bs-toggle="collapse" data-bs-target="#collapse_echoareas" aria-expanded="false" aria-controls="collapse_echoareas">Echo Areas</span>
</h3> </h3>
<div id="collapse_echoareas" class="accordion-collapse collapse" aria-labelledby="echoareas" data-bs-parent="#accordion_homepage"> <div id="collapse_echoareas" class="accordion-collapse collapse" aria-labelledby="echoareas" data-bs-parent="#accordion_homepage">
<div class="accordion-body"> <div class="accordion-body">
@if($o->echoareas->count()) @if($o->echoareas->count())
<p>This network provides the following Echomail areas:</p> <p>This network provides the following Echomail areas:</p>
<table class="table monotable w-100" id="echoarea"> <table class="table monotable w-100" id="echoarea">
<thead> <thead>
<tr> <tr>
<th class="w-75" colspan="4"></th> <th class="w-75" colspan="4"></th>
<th colspan="4" class="text-center">Messages</th> <th colspan="4" class="text-center">Messages</th>
</tr> </tr>
<tr> <tr>
<th>Echoarea</th> <th>Echoarea</th>
<th>Description</th> <th>Description</th>
<th>Last Message</th> <th>Last Message</th>
<th>Area Active</th> <th>Area Active</th>
<th class="text-end">Day</th> <th class="text-end">Day</th>
<th class="text-end">Week</th> <th class="text-end">Week</th>
<th class="text-end">Month</th> <th class="text-end">Month</th>
<th class="text-end">Total</th> <th class="text-end">Total</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@foreach ($o->echoarea_stats()->groupBy('id') as $oo) @foreach ($o->echoarea_stats()->groupBy('id') as $oo)
<tr>
<td style="width: 15%;"><a href="{{ url('echoarea/addedit',[($x=$oo->first())->id]) }}">{{ $x->name }}</a></td>
<td>{{ $x->description }}</td>
<td style="width: 15%;">{{ $x->last_message ? $x->last_message->format('Y-m-d H:i') : '-' }}</td>
<td>{{ $x->active ? 'Active' : 'Archive' }}</td>
<td class="text-end">{{ number_format($oo->where('stats','day')->pop()?->count) }}</td>
<td class="text-end">{{ number_format($oo->where('stats','week')->pop()?->count) }}</td>
<td class="text-end">{{ number_format($oo->where('stats','month')->pop()?->count) }}</td>
<td class="text-end">{{ number_format($oo->sum('count')) }}</td>
</tr>
@endforeach
</tbody>
</table>
@else
This network doesnt have any Echomail areas (yet). Perhaps you would like to create one?
@endif
</div>
</div>
</div>
<!-- File areas -->
<div class="accordion-item">
<h3 class="accordion-header">
<span class="accordion-button collapsed" id="fileareas" data-bs-toggle="collapse" data-bs-target="#collapse_fileareas" aria-expanded="false" aria-controls="collapse_fileareas">File Areas</span>
</h3>
<div id="collapse_fileareas" class="accordion-collapse collapse" aria-labelledby="fileareas" data-bs-parent="#accordion_homepage">
<div class="accordion-body">
@if($o->fileareas->count())
<p>This network provides the following File areas:</p>
<table class="table monotable" id="filearea">
<thead>
<tr>
<th>Filearea</th>
<th>Description</th>
<th>Last File Sent</th>
</tr>
</thead>
<tbody>
@foreach ($o->fileareas->sortBy('name') as $oo)
<tr>
<td style="width: 15%;"><a href="{{ url('filearea/addedit',[$oo->id]) }}">{{ $oo->name }}</a></td>
<td>{{ $oo->description }}</td>
<td style="width: 15%;">-</td>
</tr>
@endforeach
</tbody>
</table>
@else
This network doesnt have any File areas (yet). Perhaps you would like to create one?
@endif
</div>
</div>
</div>
<!-- Systems -->
<div class="accordion-item">
<h3 class="accordion-header">
<span class="accordion-button collapsed" id="systems" data-bs-toggle="collapse" data-bs-target="#collapse_systems" aria-expanded="false" aria-controls="collapse_systems">Systems</span>
</h3>
<div id="collapse_systems" class="accordion-collapse collapse" aria-labelledby="systems" data-bs-parent="#accordion_homepage">
<div class="accordion-body">
<p>The following systems are members of this network.</p>
<table class="table monotable" id="system">
<thead>
<tr> <tr>
<th>System</th> <td style="width: 15%;"><a href="{{ url('echoarea/addedit',[($x=$oo->first())->id]) }}">{{ $x->name }}</a></td>
<th>Sysop</th> <td>{{ $x->description }}</td>
<th>Location</th> <td style="width: 15%;">{{ $x->last_message ? $x->last_message->format('Y-m-d H:i') : '-' }}</td>
<th>Address</th> <td>{{ $x->active ? 'Active' : 'Archive' }}</td>
<th>Last Seen</th> <td class="text-end">{{ number_format($oo->where('stats','day')->pop()?->count) }}</td>
<td class="text-end">{{ number_format($oo->where('stats','week')->pop()?->count) }}</td>
<td class="text-end">{{ number_format($oo->where('stats','month')->pop()?->count) }}</td>
<td class="text-end">{{ number_format($oo->sum('count')) }}</td>
</tr> </tr>
</thead> @endforeach
</tbody>
<tbody> </table>
@foreach ($o->zones->sortBy('zone_id') as $oz) @else
@foreach ($oz->addresses as $ao) This network doesnt have any Echomail areas (yet). Perhaps you would like to create one?
<tr> @endif
<td><a href="{{ url('system/addedit',[$ao->system_id]) }}">{{ $ao->system->full_name($ao) }}</a> @auth<span class="float-end"><small>@if($ao->session('sespass'))<sup>{{ $ao->session('default') ? '**' : '*' }}</sup>@elseif($ao->system->setup)<sup class="success">+</sup>@endif[{{ $ao->system_id }}]</small></span>@endauth</td>
<td>{{ $ao->system->sysop }}</td>
<td>{{ $ao->system->location }}</td>
<td>{{ $ao->ftn4d }}</td>
<td>{{ $ao->system->last_session ? $ao->system->last_session->format('Y-m-d H:i') : '-' }}</td>
</tr>
@endforeach
@endforeach
</tbody>
@auth
<tfoot>
<tr>
<td colspan="5"><sup>**</sup>Default route <sup>*</sup>System defined here <sup class="success">+</sup>This system</td>
</tr>
</tfoot>
@endauth
</table>
</div>
</div>
</div> </div>
</div>
</div>
<!-- Sign up --> <!-- File areas -->
<div class="accordion-item"> <div class="accordion-item">
<h3 class="accordion-header"> <h3 class="accordion-header">
<span class="accordion-button collapsed" id="signup" data-bs-toggle="collapse" data-bs-target="#collapse_signup" aria-expanded="false" aria-controls="collapse_signup">Join Network</span> <span class="accordion-button collapsed" id="fileareas" data-bs-toggle="collapse" data-bs-target="#collapse_fileareas" aria-expanded="false" aria-controls="collapse_fileareas">File Areas</span>
</h3> </h3>
<div id="collapse_signup" class="accordion-collapse collapse" aria-labelledby="signup" data-bs-parent="#accordion_homepage"> <div id="collapse_fileareas" class="accordion-collapse collapse" aria-labelledby="fileareas" data-bs-parent="#accordion_homepage">
<div class="accordion-body"> <div class="accordion-body">
@guest @if($o->fileareas->count())
To start an application to join this network please <a href="{{ url('login') }}">login</a>. <p>This network provides the following File areas:</p>
@else <table class="table monotable" id="filearea">
@if($user->isMember($o)) <thead>
@else <tr>
This website is not ready to take applications yet, check back soon! <th>Filearea</th>
@endif <th>Description</th>
@endguest <th>Last File Sent</th>
</div> </tr>
</div> </thead>
<tbody>
@foreach ($o->fileareas->sortBy('name') as $oo)
<tr>
<td style="width: 15%;"><a href="{{ url('filearea/addedit',[$oo->id]) }}">{{ $oo->name }}</a></td>
<td>{{ $oo->description }}</td>
<td style="width: 15%;">-</td>
</tr>
@endforeach
</tbody>
</table>
@else
This network doesnt have any File areas (yet). Perhaps you would like to create one?
@endif
</div>
</div>
</div>
<!-- Systems -->
<div class="accordion-item">
<h3 class="accordion-header">
<span class="accordion-button collapsed" id="systems" data-bs-toggle="collapse" data-bs-target="#collapse_systems" aria-expanded="false" aria-controls="collapse_systems">Systems</span>
</h3>
<div id="collapse_systems" class="accordion-collapse collapse" aria-labelledby="systems" data-bs-parent="#accordion_homepage">
<div class="accordion-body">
<p>The following systems are members of this network.</p>
<table class="table monotable" id="system">
<thead>
<tr>
<th>System</th>
<th>Sysop</th>
<th>Location</th>
<th>Address</th>
<th>Last Seen</th>
</tr>
</thead>
<tbody>
@foreach ($o->zones->sortBy('zone_id') as $oz)
@foreach ($oz->addresses as $ao)
<tr>
<td><a href="{{ url('system/addedit',[$ao->system_id]) }}">{{ $ao->system->full_name($ao) }}</a> @auth<span class="float-end"><small>@if($ao->session('sespass'))<sup>{{ $ao->session('default') ? '**' : '*' }}</sup>@elseif($ao->system->setup)<sup class="success">+</sup>@endif[{{ $ao->system_id }}]</small></span>@endauth</td>
<td>{{ $ao->system->sysop }}</td>
<td>{{ $ao->system->location }}</td>
<td>{{ $ao->ftn4d }}</td>
<td>{{ $ao->system->last_session ? $ao->system->last_session->format('Y-m-d H:i') : '-' }}</td>
</tr>
@endforeach
@endforeach
</tbody>
@auth
<tfoot>
<tr>
<td colspan="5"><sup>**</sup>Default route <sup>*</sup>System defined here <sup class="success">+</sup>This system</td>
</tr>
</tfoot>
@endauth
</table>
</div>
</div>
</div>
<!-- Sign up -->
<div class="accordion-item">
<h3 class="accordion-header">
<span class="accordion-button collapsed" id="signup" data-bs-toggle="collapse" data-bs-target="#collapse_signup" aria-expanded="false" aria-controls="collapse_signup">Join Network</span>
</h3>
<div id="collapse_signup" class="accordion-collapse collapse" aria-labelledby="signup" data-bs-parent="#accordion_homepage">
<div class="accordion-body">
@guest
To start an application to join this network please <a href="{{ url('login') }}">login</a>.
@else
@if($user->isMember($o))
@else
This website is not ready to take applications yet, check back soon!
@endif
@endguest
</div> </div>
</div> </div>
</div> </div>

View File

@ -5,7 +5,7 @@
@endsection @endsection
@section('content') @section('content')
<form class="needs-validation" method="post" novalidate> <form class="row g-0 needs-validation" method="post" novalidate>
@csrf @csrf
<div class="row"> <div class="row">

View File

@ -4,9 +4,9 @@
@endsection @endsection
@section('content') @section('content')
<div class="row"> <div class="row pt-3">
<div class="col-12"> <div class="col-12">
<h1>Echomail [{{ $o->msgid ?: '-' }}] <small class="float-end">#{{ $o->id }}</small></h1> <h3>Echomail</h3>
@include('widgets.message',['msg'=>$o]) @include('widgets.message',['msg'=>$o])
</div> </div>

View File

@ -6,7 +6,7 @@
@endsection @endsection
@section('content') @section('content')
<form class="needs-validation" method="post" novalidate> <form class="row g-0 needs-validation" method="post" novalidate>
@csrf @csrf
<div class="row"> <div class="row">

View File

@ -1,6 +1,6 @@
<!-- Bootstrap & Jquery App --> <!-- Bootstrap & Jquery App -->
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js" integrity="sha512-894YE6QWD5I59HgZOGReFYm4dnWc1Qt5NtvYSaNcOP+u1T9qYdvdihz0PPSiiqn/+/3e7Jo4EaG7TubfWGUrMQ==" crossorigin="anonymous"></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js" integrity="sha512-894YE6QWD5I59HgZOGReFYm4dnWc1Qt5NtvYSaNcOP+u1T9qYdvdihz0PPSiiqn/+/3e7Jo4EaG7TubfWGUrMQ==" crossorigin="anonymous"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js" integrity="sha512-WFN04846sdKMIP5LKNphMaWzU7YpMyCU245etK3g/2ARYbPK9Ub18eG+ljU96qKRCWh+quCY7yefSmlkQw1ANQ==" crossorigin="anonymous"></script> <script type="text/javascript" src="https:///cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js" integrity="sha512-WFN04846sdKMIP5LKNphMaWzU7YpMyCU245etK3g/2ARYbPK9Ub18eG+ljU96qKRCWh+quCY7yefSmlkQw1ANQ==" crossorigin="anonymous"></script>
<!-- JavaScript Bundle with Popper --> <!-- JavaScript Bundle with Popper -->
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script> <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>

View File

@ -43,7 +43,7 @@
<dl> <dl>
<dt>Users</dt> <dt>Users</dt>
<dd><a href="{{ url('user/addedit') }}">Create</a></dd> <dd><a href="{{ url('user/addedit') }}">Create</a></dd>
<dd><a href="{{ url('user/list') }}">List</a></dd> <dd><a href="{{ url('user') }}">List</a></dd>
</dl> </dl>
@endcan @endcan
@endauth @endauth

View File

@ -32,7 +32,6 @@
</a> </a>
<div class="collapse navbar-collapse" id="user-menu-list"> <div class="collapse navbar-collapse" id="user-menu-list">
<ul class="dropdown-menu dropdown-menu-dark"> <ul class="dropdown-menu dropdown-menu-dark">
<li><a class="dropdown-item" href="{{ url('user/addedit',$user->id) }}">Account Settings</a></li>
<li><a class="dropdown-item" href="{{ url('user/system/register') }}">Register/Link System</a></li> <li><a class="dropdown-item" href="{{ url('user/system/register') }}">Register/Link System</a></li>
@can('admin') @can('admin')
<li><a class="dropdown-item @if(preg_match('#^setup#',request()->path()))thispage @endif" href="{{ url('setup') }}">Setup</a></li> <li><a class="dropdown-item @if(preg_match('#^setup#',request()->path()))thispage @endif" href="{{ url('setup') }}">Setup</a></li>

View File

@ -4,9 +4,9 @@
@endsection @endsection
@section('content') @section('content')
<div class="row"> <div class="row pt-3">
<div class="col-12"> <div class="col-12">
<h1>Netmail [{{ $o->msgid ?: '-' }}] <small class="float-end">#{{ $o->id }}</small></h1> <h3>Netmail</h3>
@include('widgets.message',['msg'=>$o]) @include('widgets.message',['msg'=>$o])
</div> </div>

View File

@ -4,7 +4,7 @@
@endsection @endsection
@section('content') @section('content')
<form class="needs-validation" method="post" enctype="multipart/form-data" novalidate> <form class="row g-0 needs-validation" method="post" enctype="multipart/form-data" novalidate>
@csrf @csrf
<div class="row"> <div class="row">

View File

@ -10,15 +10,19 @@ use App\Classes\Protocol\{Binkp,EMSI,DNS};
@endsection @endsection
@section('content') @section('content')
<form class="needs-validation" method="post" novalidate> <div class="row">
@csrf <div class="col-12">
<h2>Site Setup</h2>
</div>
</div>
<div class="row"> <div class="row pt-0">
<div class="col-12"> <div class="col-12">
<h2>Site Setup</h2> <div class="greyframe titledbox shadow0xb0">
<h2 class="cap">@if($o->exists) Update @else Initial @endif Setup</h2>
<div class="greyframe titledbox shadow0xb0"> <form class="row g-0 needs-validation" method="post" novalidate>
<h2 class="cap">@if($o->exists) Update @else Initial @endif Setup</h2> @csrf
<div class="row"> <div class="row">
<!-- System --> <!-- System -->
@ -271,7 +275,7 @@ use App\Classes\Protocol\{Binkp,EMSI,DNS};
<div class="row pt-5"> <div class="row pt-5">
<div class="col-2"> <div class="col-2">
<a href="{{ back()->getTargetUrl() }}" class="btn btn-danger">Cancel</a> <a href="{{ url('domain') }}" class="btn btn-danger">Cancel</a>
</div> </div>
<span class="col-6 mt-auto mx-auto text-center align-bottom"> <span class="col-6 mt-auto mx-auto text-center align-bottom">
@ -294,10 +298,10 @@ use App\Classes\Protocol\{Binkp,EMSI,DNS};
</div> </div>
@endcan @endcan
</div> </div>
</div> </form>
</div> </div>
</div> </div>
</form> </div>
@endsection @endsection
@section('page-css') @section('page-css')

View File

@ -7,193 +7,193 @@
<div class="row"> <div class="row">
<div class="col-12"> <div class="col-12">
<h2>System Status</h2> <h2>System Status</h2>
</div>
</div>
<div class="accordion" id="accordion_status"> <div class="accordion" id="accordion_status">
<!-- Totals --> <!-- Totals -->
<div class="accordion-item"> <div class="accordion-item">
<h3 class="accordion-header"> <h3 class="accordion-header">
<span class="accordion-button" id="totals" data-bs-toggle="collapse" data-bs-target="#collapse_totals" aria-expanded="false" aria-controls="collapse_totals">Totals</span> <span class="accordion-button" id="totals" data-bs-toggle="collapse" data-bs-target="#collapse_totals" aria-expanded="false" aria-controls="collapse_totals">Totals</span>
</h3> </h3>
<div id="collapse_totals" class="accordion-collapse collapse {{ (! $flash=session()->pull('accordion')) ? 'show' : '' }}" aria-labelledby="totals" data-bs-parent="#accordion_status"> <div id="collapse_totals" class="accordion-collapse collapse {{ (! $flash=session()->pull('accordion')) ? 'show' : '' }}" aria-labelledby="totals" data-bs-parent="#accordion_status">
<div class="accordion-body"> <div class="accordion-body">
<p>This system has processed the following so far in the last 7 days:</p> <p>This system has processed the following so far in the last 7 days:</p>
<div class="row">
<!-- Netmail -->
<div class="col-3">
<div class="card bg-success">
<div class="card-header p-2">
<span class="card-title w-100 text-dark" style="font-size: 125%;"><i class="bi bi-envelope-at"></i> Netmail
<button type="button" class="btn float-end me-0" style="background-color: darkgreen; color: white;">{{ number_format(($x=\App\Models\Netmail::where('netmails.created_at','>=',\Carbon\Carbon::now()->subWeek()->startOfDay())
->join('addresses',['addresses.id'=>'netmails.fftn_id'])
->join('zones',['zones.id'=>'addresses.zone_id'])
->join('domains',['domains.id'=>'zones.domain_id'])
->orderBy('domains.name')
->with('fftn.zone.domain')
->get())
->count()) }}
</button>
</span>
</div>
@if($x->count())
<div class="card-body text-dark">
<p class="card-text">Networks:</p>
<ul class="p-0 m-0">
@foreach($x->groupBy('fftn.zone_id') as $oo)
<li class="m-0">{{ $oo->first()->fftn->zone->domain->name }}: {{ number_format($oo->count()) }}</li>
@endforeach
</ul>
</div>
@endif
</div>
</div>
<!-- Echomail -->
<div class="col-3">
<div class="card bg-primary">
<div class="card-header p-2">
<span class="card-title w-100 text-dark" style="font-size: 125%;"><i class="bi bi-envelope"></i> Echomail
<button type="button" class="btn float-end me-0" style="background-color: darkblue; color: white;">{{ number_format(($x=\App\Models\Echomail::where('echomails.created_at','>=',\Carbon\Carbon::now()->subWeek()->startOfDay())
->join('addresses',['addresses.id'=>'echomails.fftn_id'])
->join('zones',['zones.id'=>'addresses.zone_id'])
->join('domains',['domains.id'=>'zones.domain_id'])
->orderBy('domains.name')
->orderBy('zones.zone_id')
->with('fftn.zone.domain')
->get())
->count()) }}
</button>
</span>
</div>
@if($x->count())
<div class="card-body text-dark">
<p class="card-text">Networks:</p>
<ul class="p-0 m-0">
@foreach($x->groupBy('fftn.zone_id') as $oo)
<li class="m-0">{{ sprintf('Z%d (%s)',$oo->first()->fftn->zone->zone_id,$oo->first()->fftn->zone->domain->name) }}: {{ number_format($oo->count()) }}</li>
@endforeach
</ul>
</div>
@endif
</div>
</div>
<!-- File -->
<div class="col-3">
<div class="card bg-danger">
<div class="card-header p-2">
<span class="card-title w-100 text-dark" style="font-size: 125%;"><i class="bi bi-folder"></i> Files
<button type="button" class="btn float-end me-0" style="background-color: darkred; color: white;">{{ number_format(($x=\App\Models\File::where('files.created_at','>=',\Carbon\Carbon::now()->subWeek()->startOfDay())
->join('addresses',['addresses.id'=>'files.fftn_id'])
->join('zones',['zones.id'=>'addresses.zone_id'])
->join('domains',['domains.id'=>'zones.domain_id'])
->orderBy('domains.name')
->with('fftn.zone.domain')
->get())
->count()) }}
</button>
</span>
</div>
@if($x->count())
<div class="card-body text-dark">
<p class="card-text">Networks:</p>
<ul class="p-0 m-0">
@foreach($x->groupBy('fftn.zone_id') as $oo)
<li class="m-0">{{ sprintf('Z%d (%s)',$oo->first()->fftn->zone->zone_id,$oo->first()->fftn->zone->domain->name) }}: {{ number_format($oo->count()) }}</li>
@endforeach
</ul>
</div>
@endif
</div>
</div>
<!-- DNS -->
<div class="col-3">
<div class="row"> <div class="row">
<!-- Netmail --> <div class="col-12">
<div class="col-3"> <div class="card bg-light">
<div class="card bg-success">
<div class="card-header p-2"> <div class="card-header p-2">
<span class="card-title w-100 text-dark" style="font-size: 125%;"><i class="bi bi-envelope-at"></i> Netmail <span class="card-title w-100 text-dark" style="font-size: 125%;"><i class="bi bi-pc-display"></i> Systems
<button type="button" class="btn float-end me-0" style="background-color: darkgreen; color: white;">{{ number_format(($x=\App\Models\Netmail::where('netmails.created_at','>=',\Carbon\Carbon::now()->subWeek()->startOfDay()) <button type="button" class="btn float-end me-0" style="background-color: black; color: white;">
->join('addresses',['addresses.id'=>'netmails.fftn_id']) {{ number_format(\App\Models\System::where('last_session','>=',\Carbon\Carbon::now()->subWeek()->startOfDay())->count()) }}
->join('zones',['zones.id'=>'addresses.zone_id'])
->join('domains',['domains.id'=>'zones.domain_id'])
->orderBy('domains.name')
->with('fftn.zone.domain')
->get())
->count()) }}
</button> </button>
</span> </span>
</div> </div>
@if($x->count())
<div class="card-body text-dark">
<p class="card-text">Networks:</p>
<ul class="p-0 m-0">
@foreach($x->groupBy('fftn.zone_id') as $oo)
<li class="m-0">{{ $oo->first()->fftn->zone->domain->name }}: {{ number_format($oo->count()) }}</li>
@endforeach
</ul>
</div>
@endif
</div> </div>
</div> </div>
</div>
<!-- Echomail --> <div class="row pt-3">
<div class="col-3"> <div class="col-12">
<div class="card bg-primary"> <div class="card bg-secondary">
<div class="card-header p-2"> <div class="card-header p-2">
<span class="card-title w-100 text-dark" style="font-size: 125%;"><i class="bi bi-envelope"></i> Echomail <span class="card-title w-100 text-dark" style="font-size: 125%;"><i class="bi bi-globe"></i> DNS Queries
<button type="button" class="btn float-end me-0" style="background-color: darkblue; color: white;">{{ number_format(($x=\App\Models\Echomail::where('echomails.created_at','>=',\Carbon\Carbon::now()->subWeek()->startOfDay()) <button type="button" class="btn float-end me-0" style="background-color: black; color: white;">N/A</button>
->join('addresses',['addresses.id'=>'echomails.fftn_id'])
->join('zones',['zones.id'=>'addresses.zone_id'])
->join('domains',['domains.id'=>'zones.domain_id'])
->orderBy('domains.name')
->orderBy('zones.zone_id')
->with('fftn.zone.domain')
->get())
->count()) }}
</button>
</span> </span>
</div> </div>
@if($x->count())
<div class="card-body text-dark">
<p class="card-text">Networks:</p>
<ul class="p-0 m-0">
@foreach($x->groupBy('fftn.zone_id') as $oo)
<li class="m-0">{{ sprintf('Z%d (%s)',$oo->first()->fftn->zone->zone_id,$oo->first()->fftn->zone->domain->name) }}: {{ number_format($oo->count()) }}</li>
@endforeach
</ul>
</div>
@endif
</div>
</div>
<!-- File -->
<div class="col-3">
<div class="card bg-danger">
<div class="card-header p-2">
<span class="card-title w-100 text-dark" style="font-size: 125%;"><i class="bi bi-folder"></i> Files
<button type="button" class="btn float-end me-0" style="background-color: darkred; color: white;">{{ number_format(($x=\App\Models\File::where('files.created_at','>=',\Carbon\Carbon::now()->subWeek()->startOfDay())
->join('addresses',['addresses.id'=>'files.fftn_id'])
->join('zones',['zones.id'=>'addresses.zone_id'])
->join('domains',['domains.id'=>'zones.domain_id'])
->orderBy('domains.name')
->with('fftn.zone.domain')
->get())
->count()) }}
</button>
</span>
</div>
@if($x->count())
<div class="card-body text-dark">
<p class="card-text">Networks:</p>
<ul class="p-0 m-0">
@foreach($x->groupBy('fftn.zone_id') as $oo)
<li class="m-0">{{ sprintf('Z%d (%s)',$oo->first()->fftn->zone->zone_id,$oo->first()->fftn->zone->domain->name) }}: {{ number_format($oo->count()) }}</li>
@endforeach
</ul>
</div>
@endif
</div>
</div>
<!-- DNS -->
<div class="col-3">
<div class="row">
<div class="col-12">
<div class="card bg-light">
<div class="card-header p-2">
<span class="card-title w-100 text-dark" style="font-size: 125%;"><i class="bi bi-pc-display"></i> Systems
<button type="button" class="btn float-end me-0" style="background-color: black; color: white;">
{{ number_format(\App\Models\System::where('last_session','>=',\Carbon\Carbon::now()->subWeek()->startOfDay())->count()) }}
</button>
</span>
</div>
</div>
</div>
</div>
<div class="row pt-3">
<div class="col-12">
<div class="card bg-secondary">
<div class="card-header p-2">
<span class="card-title w-100 text-dark" style="font-size: 125%;"><i class="bi bi-globe"></i> DNS Queries
<button type="button" class="btn float-end me-0" style="background-color: black; color: white;">N/A</button>
</span>
</div>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div>
</div>
<!-- Uncollected Mail --> <!-- Uncollected Mail -->
<div class="accordion-item"> <div class="accordion-item">
<h3 class="accordion-header"> <h3 class="accordion-header">
<span class="accordion-button collapsed" id="uncollected" data-bs-toggle="collapse" data-bs-target="#collapse_uncollected" aria-expanded="true" aria-controls="collapse_uncollected">Uncollected Mail</span> <span class="accordion-button collapsed" id="uncollected" data-bs-toggle="collapse" data-bs-target="#collapse_uncollected" aria-expanded="true" aria-controls="collapse_uncollected">Uncollected Mail</span>
</h3> </h3>
<div id="collapse_uncollected" class="accordion-collapse collapse {{ ($flash==='uncollected') ? 'show' : '' }}" aria-labelledby="uncollected" data-bs-parent="#accordion_status"> <div id="collapse_uncollected" class="accordion-collapse collapse {{ ($flash==='uncollected') ? 'show' : '' }}" aria-labelledby="uncollected" data-bs-parent="#accordion_status">
<div class="accordion-body"> <div class="accordion-body">
<div class="row"> <div class="row">
<div class="col-12"> <div class="col-12">
<p>Nodes with uncollected mail as at <strong class="highlight">{{ $date }}</strong>:</p> <p>Nodes with uncollected mail as at <strong class="highlight">{{ $date }}</strong>:</p>
<table class="table monotable w-100" id="mailfiles"> <table class="table monotable w-100" id="mailfiles">
<thead> <thead>
<tr> <tr>
<th>Network</th> <th>Network</th>
<th>System</th> <th>System</th>
<th>Address</th> <th>Address</th>
<th class="text-end">Echomails</th> <th class="text-end">Echomails</th>
<th class="text-end">Netmails</th> <th class="text-end">Netmails</th>
<th class="text-end">Files</th> <th class="text-end">Files</th>
<th>Last Session</th> <th>Last Session</th>
<th>Poll Mode</th> <th>Poll Mode</th>
<th>Auto Hold</th> <th>Auto Hold</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@foreach($uncollected as $o) @foreach($uncollected as $o)
<tr> <tr>
<td>{{ $o->zone->domain->name }}</td> <td>{{ $o->zone->domain->name }}</td>
<td> <td>
<a href="{{ url('system/addedit',$o->system_id) }}">{{ $o->system->name }}</a> <a href="{{ url('system/addedit',$o->system_id) }}">{{ $o->system->name }}</a>
@if (($x=$o->parent()) && ($x->id !== $o->id)) @if (($x=$o->parent()) && ($x->id !== $o->id))
<br><small>[via <a href="{{ url('system/addedit',$x->system_id) }}">{{ $x->ftn4d }}</a>]</small> <br><small>[via <a href="{{ url('system/addedit',$x->system_id) }}">{{ $x->ftn4d }}</a>]</small>
@endif @endif
</td> </td>
<td>{{ $o->ftn4d }}</td> <td>{{ $o->ftn4d }}</td>
<td class="text-end">{{ number_format($o->uncollected_echomail ?? 0) }}</td> <td class="text-end">{{ number_format($o->uncollected_echomail ?? 0) }}</td>
<td class="text-end">{{ number_format($o->uncollected_netmail ?? 0) }}</td> <td class="text-end">{{ number_format($o->uncollected_netmail ?? 0) }}</td>
<td class="text-end">{{ number_format($o->uncollected_files ?? 0) }}</td> <td class="text-end">{{ number_format($o->uncollected_files ?? 0) }}</td>
<td>{{ $o->system->last_session?->format('Y-m-d H:i') }}</td> <td>{{ $o->system->last_session?->format('Y-m-d H:i') }}</td>
<td>{{ is_null($o->system->pollmode) ? 'HOLD' : ($o->system->pollmode ? 'CRASH' : 'DAILY') }}</td> <td>{{ is_null($o->system->pollmode) ? 'HOLD' : ($o->system->pollmode ? 'CRASH' : 'DAILY') }}</td>
<td>{{ $o->system->autohold ? 'YES' : 'NO' }}</td> <td>{{ $o->system->autohold ? 'YES' : 'NO' }}</td>
</tr> </tr>
@endforeach @endforeach
</tbody> </tbody>
</table> </table>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -7,10 +7,8 @@
@section('content') @section('content')
@if($o->exists) @if($o->exists)
<h1> <h1>{{ $o->name }}@if($o->setup)<sup class="success" style="text-shadow: 0 0; font-size: 50%; top: -1em;">*</sup>@endif</h1>
{{ $o->name }}@if($o->setup)<sup class="success">*</sup>@endif @if($o->setup)<sup class="success" style="float:right;top:-2em;">* This Host</sup>@endif
@if($o->setup)<small class="success float-end">* This Host</small>@endif
</h1>
@endif @endif
@if($o->zcs->count()) @if($o->zcs->count())
@ -27,7 +25,7 @@
<div id="collapse_system" class="accordion-collapse collapse {{ (! $flash=session()->pull('accordion')) ? 'show' : '' }}" aria-labelledby="system" data-bs-parent="#accordion_homepage"> <div id="collapse_system" class="accordion-collapse collapse {{ (! $flash=session()->pull('accordion')) ? 'show' : '' }}" aria-labelledby="system" data-bs-parent="#accordion_homepage">
<div class="accordion-body"> <div class="accordion-body">
@include('system.widget.form-system') @include('system.form-system')
</div> </div>
</div> </div>
</div> </div>
@ -40,135 +38,134 @@
<div id="collapse_addresses" class="accordion-collapse collapse {{ ($flash=='address') ? 'show' : '' }}" aria-labelledby="addresses" data-bs-parent="#accordion_homepage"> <div id="collapse_addresses" class="accordion-collapse collapse {{ ($flash=='address') ? 'show' : '' }}" aria-labelledby="addresses" data-bs-parent="#accordion_homepage">
<div class="accordion-body"> <div class="accordion-body">
<div class="row"> <p>FidoNet addresses are constructed in the format <strong class="highlight">zone</strong>:<strong class="highlight">net</strong>/<strong class="highlight">node</strong>.<strong class="highlight">point</strong><span>@</span><strong class="highlight">domain</strong>.</p>
<div class="col-12">
<p>FidoNet addresses are constructed in the format <strong class="highlight">zone</strong>:<strong class="highlight">net</strong>/<strong class="highlight">node</strong>.<strong class="highlight">point</strong><span>@</span><strong class="highlight">domain</strong>.</p>
<div class="accordion accordion-flush" id="accordion_ftnaddress"> <div class="accordion accordion-flush" id="accordion_ftnaddress">
<h4 class="accordion-header"> <h4 class="accordion-header">
<span class="accordion-button collapsed" id="ftnaddress" data-bs-toggle="collapse" data-bs-target="#collapse_ftnaddresses" aria-expanded="false" aria-controls="collapse_addresses">Fidonet Addressing</span> <span class="accordion-button collapsed" id="ftnaddress" data-bs-toggle="collapse" data-bs-target="#collapse_ftnaddresses" aria-expanded="false" aria-controls="collapse_addresses">Fidonet Addressing</span>
</h4> </h4>
<div id="collapse_ftnaddresses" class="accordion-collapse collapse" aria-labelledby="ftnaddress" data-bs-parent="#accordion_ftnaddress">
<div class="accordion-body">
<p>FidoNet system are also assigned some roles, and in some cases, those roles have a particular address format:</p>
<table class="table monotable">
<thead>
<tr>
<th>Role</th>
<th>Address Format</th>
</tr>
</thead>
<tbody>
<tr>
<td>Zone <small>(optional)</small></td>
<td>
<strong class="highlight">ZONE</strong>:0/0.0, where the net, node and point values are zero. Zones normally have 1 or more Regions and/or Hosts.<br><br>
<small>(Systems that do not configure other systems with a zone, assume that that other system is in the same zone as the system being configured.)</small>
</td>
</tr>
<tr>
<td>Region <small>(optional)</small></td>
<td>
zone:<strong class="highlight">REGION</strong>/0.0, where the zone indicates which zone the region is in. The node and point values are zero. Regions normally have 1 or more Hosts.<br><br>
<small>Fidonet software normally doesnt configure the region address per-se. It is used by the mailer to receive packets destined to it by routing, in transition to the final destination. The region number must be unique with a zone.</small>
</td>
</tr>
<tr>
<td>Host <small>(mandatory)</small></td>
<td>
zone:<strong class="highlight">HOST</strong>/0.0, where the zone indicates which zone the host is in. The node and point values are zero. The Host system is normally configured with an additional address, where the NET address is the same and the NODE number that is greater than zero. Hosts may may zero or more Hubs and 1 or more Nodes.<br><br>
<small>The host number must be unique within a zone, which implies that it cannot be the same as a region, if regions are used.</small>
</td>
</tr>
<tr>
<td>Hub <small>(optional)</small></td>
<td>
zone:net/<strong class="highlight">NODE</strong>.0, where the zone/net indicates which zone/net the hub is in. The system(s) in the nodelist below a Hub are fed from that hub from a routing perspective.<br><br>
<small>The node is unique within the net and point is zero.</small>
</td>
</tr>
<tr>
<td>Node <small>(required)</small></td>
<td>
zone:net/<strong class="highlight">NODE</strong>.0, where the zone/net indicates which zone/net the node is in.<br><br>
<small>The node is unique within the net and point is zero.</small>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
@if($o->addresses->count())
<p>This system has the following addresses assigned to it:</p>
<div id="collapse_ftnaddresses" class="accordion-collapse collapse" aria-labelledby="ftnaddress" data-bs-parent="#accordion_ftnaddress">
<div class="accordion-body">
<p>FidoNet system are also assigned some roles, and in some cases, those roles have a particular address format:</p>
<table class="table monotable"> <table class="table monotable">
<thead> <thead>
<tr> <tr>
<th>Address</th> <th>Role</th>
<th>Active</th> <th>Address Format</th>
<th>Security</th>
<th colspan="2">Role</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@foreach ($o->addresses->sortBy(function($item) { return sprintf('%04x%04x%04x%04x%04x',$item->zone->zone_id,$item->region_id,$item->host_id,$item->node_id,$item->point_id); }) as $oo) <tr>
<tr> <td>Zone <small>(optional)</small></td>
<td @if($oo->trashed()) class="trashed" @elseif (! $oo->active) class="inactive" @endif>{{ $oo->ftn }}<span class="float-end"><i title="@if($oo->validated)Mail flowing @else Mail held @endif" class="bi @if($oo->validated)bi-activity @else bi-radioactive @endif"></i></span></td> <td>
<td>{{ $oo->active ? 'YES' : 'NO' }}</td> <strong class="highlight">ZONE</strong>:0/0.0, where the net, node and point values are zero. Zones normally have 1 or more Regions and/or Hosts.<br><br>
<td class="text-end">{{ $oo->security }}</td> <small>(Systems that do not configure other systems with a zone, assume that that other system is in the same zone as the system being configured.)</small>
<td>{{ $oo->role_name }}</td> </td>
<td class="nowrap actions"> </tr>
@can('admin',$oo) <tr>
@if(! $oo->active_domain) <td>Region <small>(optional)</small></td>
<!-- No options --> <td>
<a href="javascript:;" title="Net Disabled"><i class="bi bi-slash-square"></i></a> zone:<strong class="highlight">REGION</strong>/0.0, where the zone indicates which zone the region is in. The node and point values are zero. Regions normally have 1 or more Hosts.<br><br>
@elseif($oo->trashed()) <small>Fidonet software normally doesnt configure the region address per-se. It is used by the mailer to receive packets destined to it by routing, in transition to the final destination. The region number must be unique with a zone.</small>
<a href="{{ url('system/address/rec',[$oo->id]) }}" title="Restore Address"><i class="bi bi-bandaid"></i></a> </td>
<a href="{{ url('system/address/pur',[$oo->id]) }}" title="Purge Address" class="purge"><i class="bi bi-scissors"></i></a> </tr>
@else <tr>
<a href="{{ url('system/address/mod',[$oo->id]) }}" data-id="{{ $oo->id }}" title="Modify Address" class="modaddress" aria-readonly="true"><i class="bi bi-pencil-square"></i></a> <td>Host <small>(mandatory)</small></td>
<a href="{{ url('system/address/sus',[$oo->id]) }}" title="@if($oo->active)Pause @else Activate @endif Address"><i class="bi @if($oo->active)bi-pause-circle @else bi-play-circle @endif"></i></a> <td>
<a href="{{ url('system/address/mov',[$o->id,$oo->id]) }}" title="Move Address to another System"><i class="bi bi-arrow-right-square"></i></a> zone:<strong class="highlight">HOST</strong>/0.0, where the zone indicates which zone the host is in. The node and point values are zero. The Host system is normally configured with an additional address, where the NET address is the same and the NODE number that is greater than zero. Hosts may may zero or more Hubs and 1 or more Nodes.<br><br>
<a href="{{ url('system/address/del',[$oo->id]) }}" title="Delete Address"><i class="bi bi-trash"></i></a> <small>The host number must be unique within a zone, which implies that it cannot be the same as a region, if regions are used.</small>
@if ((\App\Models\Address::NODE_HC|\App\Models\Address::NODE_ACTIVE) & $oo->role) </td>
<a href="{{ url('system/address/pro',[$oo->id]) }}" title="Promote Address"><i class="bi bi-arrow-up-square"></i></a> </tr>
@endif <tr>
@if ((\App\Models\Address::NODE_NC|\App\Models\Address::NODE_HC) & $oo->role) <td>Hub <small>(optional)</small></td>
<a href="{{ url('system/address/dem',[$oo->id]) }}" title="Demote Address"><i class="bi bi-arrow-down-square"></i></a> <td>
@endif zone:net/<strong class="highlight">NODE</strong>.0, where the zone/net indicates which zone/net the hub is in. The system(s) in the nodelist below a Hub are fed from that hub from a routing perspective.<br><br>
@endif <small>The node is unique within the net and point is zero.</small>
@endcan </td>
</td> </tr>
</tr> <tr>
@endforeach <td>Node <small>(required)</small></td>
<td>
zone:net/<strong class="highlight">NODE</strong>.0, where the zone/net indicates which zone/net the node is in.<br><br>
<small>The node is unique within the net and point is zero.</small>
</td>
</tr>
</tbody> </tbody>
</table> </table>
@endif
</div>
</div>
@error('address')
<div class="row pb-5">
<div class="col-12">
<span class="btn btn-sm btn-danger" role="alert" style="text-align: left;">
{!! $message !!}
</span>
</div>
</div>
@enderror
@can('admin',$o)
<div class="row pb-2">
<div class="col-12">
@include('system.widget.form-address')
</div> </div>
</div> </div>
</div>
@if($o->addresses->count())
<p>This system has the following addresses assigned to it:</p>
<table class="table monotable">
<thead>
<tr>
<th>Address</th>
<th>Active</th>
<th>Security</th>
<th colspan="2">Role</th>
</tr>
</thead>
<tbody>
@foreach ($o->addresses->sortBy(function($item) { return sprintf('%04x%04x%04x%04x%04x',$item->zone->zone_id,$item->region_id,$item->host_id,$item->node_id,$item->point_id); }) as $oo)
<tr>
<td @if($oo->trashed()) class="trashed" @elseif (! $oo->active) class="inactive" @endif>{{ $oo->ftn }} <span class="float-end"><i title="@if($oo->validated)Mail flowing @else Mail held @endif" class="bi @if($oo->validated)bi-activity @else bi-radioactive @endif"></i></span></td>
<td>{{ $oo->active ? 'YES' : 'NO' }}</td>
<td class="text-end">{{ $oo->security }}</td>
<td>{{ $oo->role_name }}</td>
<td class="nowrap actions">
@can('admin',$oo)
@if(! $oo->active_domain)
<!-- No options -->
<a href="javascript:;" title="Net Disabled"><i class="bi bi-slash-square"></i></a>
@elseif($oo->trashed())
<a href="{{ url('system/address/rec',[$oo->id]) }}" title="Restore Address"><i class="bi bi-bandaid"></i></a>
<a href="{{ url('system/address/pur',[$oo->id]) }}" title="Purge Address" class="purge"><i class="bi bi-scissors"></i></a>
@else
<a href="{{ url('system/address/mod',[$oo->id]) }}" data-id="{{ $oo->id }}" title="Modify Address" class="modaddress" aria-readonly="true"><i class="bi bi-pencil-square"></i></a>
<a href="{{ url('system/address/sus',[$oo->id]) }}" title="@if($oo->active)Pause @else Activate @endif Address"><i class="bi @if($oo->active)bi-pause-circle @else bi-play-circle @endif"></i></a>
<a href="{{ url('system/address/mov',[$o->id,$oo->id]) }}" title="Move Address to another System"><i class="bi bi-arrow-right-square"></i></a>
<a href="{{ url('system/address/del',[$oo->id]) }}" title="Delete Address"><i class="bi bi-trash"></i></a>
@if ((\App\Models\Address::NODE_HC|\App\Models\Address::NODE_ACTIVE) & $oo->role)
<a href="{{ url('system/address/pro',[$oo->id]) }}" title="Promote Address"><i class="bi bi-arrow-up-square"></i></a>
@endif
@if ((\App\Models\Address::NODE_NC|\App\Models\Address::NODE_HC) & $oo->role)
<a href="{{ url('system/address/dem',[$oo->id]) }}" title="Demote Address"><i class="bi bi-arrow-down-square"></i></a>
@endif
@endif
@endcan
</td>
</tr>
@endforeach
</tbody>
</table>
@error('susaddress')
<span class="btn btn-sm btn-danger" role="alert" style="text-align: left;">
{!! $message !!}
</span>
@enderror
@error('demaddress')
<span class="btn btn-sm btn-danger" role="alert" style="text-align: left;">
{!! $message !!}
</span>
@enderror
@error('proaddress')
<span class="btn btn-sm btn-danger" role="alert" style="text-align: left;">
{!! $message !!}
</span>
@enderror
@endif
@can('admin',$o)
@include('system.form-address')
@else @else
You'll need to ask an admin to assign addresses. You'll need to ask an admin to assign addresses.
@ -207,27 +204,27 @@
<tbody> <tbody>
@foreach ($o->sessions->sortBy('zone_id') as $oo) @foreach ($o->sessions->sortBy('zone_id') as $oo)
<tr> <tr>
<td>{{ $oo->zone_id }}<span>@</span>{{ $oo->domain->name }}</td> <td>{{ $oo->zone_id }}<span>@</span>{{ $oo->domain->name }}</td>
<td style="text-align: center;"> <td style="text-align: center;">
@if(($x=$oo->systems->where('pivot.default',TRUE))->count() && ($x->first()->id !== $o->id)) @if(($x=$oo->systems->where('pivot.default',TRUE))->count() && ($x->first()->id !== $o->id))
<i class="bi bi-dash-square"></i> <i class="bi bi-dash-square"></i>
@else @else
<span class="default" itemid="{{ $oo->id }}"><i class="bi bi-{{ $x->count() ? 'check-square' : 'square' }}"></i></span> <span class="default" itemid="{{ $oo->id }}"><i class="bi bi-{{ $x->count() ? 'check-square' : 'square' }}"></i></span>
@endif @endif
</td> </td>
<td>{{ $oo->pivot->sespass }}</td> <td>{{ $oo->pivot->sespass }}</td>
<td>{{ $oo->pivot->pktpass }}</td> <td>{{ $oo->pivot->pktpass }}</td>
<td>{{ $oo->pivot->ticpass }}</td> <td>{{ $oo->pivot->ticpass }}</td>
<td>{{ $oo->pivot->fixpass }}</td> <td>{{ $oo->pivot->fixpass }}</td>
<td style="width: 70px;"> <td style="width: 70px;">
{{-- {{--
<a href="{{ url('system/session/mod',[$oo->id]) }}" title="Modify Details" class="modify"><i class="bi bi-pen"></i></a> <a href="{{ url('system/session/mod',[$oo->id]) }}" title="Modify Details" class="modify"><i class="bi bi-pen"></i></a>
--}} --}}
<a href="{{ url('system/session/del',[$o->id,$oo->id]) }}" title="Delete Details" class="purge"><i class="bi bi-trash"></i></a> <a href="{{ url('system/session/del',[$o->id,$oo->id]) }}" title="Delete Details" class="purge"><i class="bi bi-trash"></i></a>
<a href="{{ url('system/areafix',[$o->id,$oo->id]) }}" title="Areafix/Filefix"><i class="bi bi-envelope-paper"></i></a> <a href="{{ url('system/areafix',[$o->id,$oo->id]) }}" title="Areafix/Filefix"><i class="bi bi-envelope-paper"></i></a>
</td> </td>
</tr> </tr>
@endforeach @endforeach
</tbody> </tbody>
</table> </table>
@ -235,7 +232,7 @@
<p>No session details exist</p> <p>No session details exist</p>
@endif @endif
@include('system.widget.form-session') @include('system.form-session')
</div> </div>
</div> </div>
</div> </div>
@ -249,7 +246,7 @@
<div id="collapse_echoarea" class="accordion-collapse collapse {{ ($flash=='echoarea') ? 'show' : '' }}" aria-labelledby="echoarea" data-bs-parent="#accordion_homepage"> <div id="collapse_echoarea" class="accordion-collapse collapse {{ ($flash=='echoarea') ? 'show' : '' }}" aria-labelledby="echoarea" data-bs-parent="#accordion_homepage">
<div class="accordion-body"> <div class="accordion-body">
<p>This system can subscribe to the following echoareas:</p> <p>This system can subscribe to the following echoareas:</p>
@include('system.widget.form-echoarea') @include('system.form-echoarea')
</div> </div>
</div> </div>
</div> </div>
@ -263,7 +260,7 @@
<div id="collapse_filearea" class="accordion-collapse collapse {{ ($flash=='filearea') ? 'show' : '' }}" aria-labelledby="filearea" data-bs-parent="#accordion_homepage"> <div id="collapse_filearea" class="accordion-collapse collapse {{ ($flash=='filearea') ? 'show' : '' }}" aria-labelledby="filearea" data-bs-parent="#accordion_homepage">
<div class="accordion-body"> <div class="accordion-body">
<p>This system can subscribe to the following fileareas:</p> <p>This system can subscribe to the following fileareas:</p>
@include('system.widget.form-filearea') @include('system.form-filearea')
</div> </div>
</div> </div>
</div> </div>
@ -641,9 +638,8 @@
</div> </div>
</div> </div>
@endif @endif
@else @else
@include('system.widget.form-system') @include('system.form-system')
@endif @endif
</div> </div>
@ -661,18 +657,18 @@
@endsection @endsection
@section('page-scripts') @section('page-scripts')
<script type="text/javascript"> <script type="text/javascript">
$(document).ready(function () { $(document).ready(function() {
$('.default').click(function () { $('.default').click(function() {
var item = this; var item = this;
icon = $(item).find('i'); icon = $(item).find('i');
$.ajax({ $.ajax({
type: 'POST', type: 'POST',
data: {sid: {{$o->id}}, _token: '{{csrf_token()}}', set: (icon.hasClass('bi-square') ? 1 : 0)}, data: {sid: {{$o->id}},_token: '{{csrf_token()}}',set:(icon.hasClass('bi-square') ? 1 : 0)},
beforeSend: function () { beforeSend: function() {
$(item).find('i').addClass('spinner-grow spinner-grow-sm'); $(item).find('i').addClass('spinner-grow spinner-grow-sm');
}, },
success: function () { success: function() {
if (icon.hasClass('bi-square')) { if (icon.hasClass('bi-square')) {
icon.removeClass('bi-square'); icon.removeClass('bi-square');
icon.addClass('bi-check-square'); icon.addClass('bi-check-square');
@ -683,13 +679,13 @@
$(item).find('i').removeClass('spinner-grow spinner-grow-sm'); $(item).find('i').removeClass('spinner-grow spinner-grow-sm');
}, },
error: function (e) { error: function(e) {
$(item).find('i').removeClass('spinner-grow spinner-grow-sm'); $(item).find('i').removeClass('spinner-grow spinner-grow-sm');
if (e.status != 412) if (e.status != 412)
alert('That didnt work? Please try again....'); alert('That didnt work? Please try again....');
}, },
url: '{{ url('zone/api/default') }}/' + item.attributes.itemid.nodeValue, url: '{{ url('zone/api/default') }}/'+item.attributes.itemid.nodeValue,
cache: false cache: false
}) })
}); });

View File

@ -6,66 +6,66 @@
@endsection @endsection
@section('content') @section('content')
<form class="needs-validation" method="post" novalidate> <div class="row pt-0">
@csrf <div class="col-12">
<h2>Merge Address {{ $o->ftn }}</h2>
<p>{{ $o->system->sysop }} : {{ $o->system->name }}</p>
</div>
<div class="row"> <div class="col-12">
<div class="col-12"> <form method="POST">
<h2>Merge Address {{ $o->ftn }}</h2> @csrf
<p>{{ $o->system->sysop }} : {{ $o->system->name }}</p>
</div>
<div class="col-12">
<table class="table monotable"> <table class="table monotable">
<thead> <thead>
<tr> <tr>
<th>F</th> <th>F</th>
<th>T</th> <th>T</th>
<th>ID</th> <th>ID</th>
<th>FTN</th> <th>FTN</th>
<th>ACTIVE</th> <th>ACTIVE</th>
<th>Messages</th> <th>Messages</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@foreach ($oo as $ao) @foreach ($oo as $ao)
<tr> <tr>
<td><input type="radio" name="src" value="{{ $ao->id }}"></td> <td><input type="radio" name="src" value="{{ $ao->id }}"></td>
<td><input type="radio" name="dst" value="{{ $ao->id }}"></td> <td><input type="radio" name="dst" value="{{ $ao->id }}"></td>
<th>{{ $ao->id }} {{ $ao->system_id }}:<a href="{{ url('system/addedit',$ao->system_id) }}">{{ $ao->system->name }}</a></th> <th>{{ $ao->id }} {{ $ao->system_id }}:<a href="{{ url('system/addedit',$ao->system_id) }}">{{ $ao->system->name }}</a></th>
<th>{{ $ao->ftn }}</th> <th>{{ $ao->ftn }}</th>
<td> <td>
@if($ao->trashed()) @if($ao->trashed())
<a href="{{ url('system/address/rec',[$ao->id]) }}" title="Restore Address"><i class="bi bi-bandaid"></i></a> <a href="{{ url('system/address/rec',[$ao->id]) }}" title="Restore Address"><i class="bi bi-bandaid"></i></a>
<a href="{{ url('system/address/pur',[$ao->id]) }}" title="Purge Address" class="purge"><i class="bi bi-scissors"></i></a> <a href="{{ url('system/address/pur',[$ao->id]) }}" title="Purge Address" class="purge"><i class="bi bi-scissors"></i></a>
@else @else
<a href="{{ url('system/address/sus',[$ao->id]) }}" title="@if($ao->active)Pause @else Activate @endif Address"><i class="bi @if($ao->active)bi-pause-circle @else bi-play-circle @endif"></i></a> <a href="{{ url('system/address/sus',[$ao->id]) }}" title="@if($ao->active)Pause @else Activate @endif Address"><i class="bi @if($ao->active)bi-pause-circle @else bi-play-circle @endif"></i></a>
<a href="{{ url('system/address/mov',[$ao->system_id,$ao->id]) }}" title="Move Address to another System"><i class="bi bi-arrow-right-square"></i></a> <a href="{{ url('system/address/mov',[$ao->system_id,$ao->id]) }}" title="Move Address to another System"><i class="bi bi-arrow-right-square"></i></a>
<a href="{{ url('system/address/del',[$ao->id]) }}" title="Delete Address"><i class="bi bi-trash"></i></a> <a href="{{ url('system/address/del',[$ao->id]) }}" title="Delete Address"><i class="bi bi-trash"></i></a>
@endif @endif
</td> </td>
<td> <td>
<ul> <ul>
@foreach(\App\Models\Echomail::select(['id','msgid','from','msg','echoarea_id']) @foreach(\App\Models\Echomail::select(['id','msgid','from','msg','echoarea_id'])
->where('fftn_id',$ao->id) ->where('fftn_id',$ao->id)
->orderBy('created_at','DESC') ->orderBy('created_at','DESC')
->with('echoarea') ->with('echoarea')
->limit(5) ->limit(5)
->get() as $eo) ->get() as $eo)
<li class="pb-4">{{ sprintf('%s-%04d: %s (%s) %s',$eo->echoarea->name,$eo->id,$eo->from,$eo->msgid,$eo->msg) }}</li> <li class="pb-4">{{ sprintf('%s-%04d: %s (%s) %s',$eo->echoarea->name,$eo->id,$eo->from,$eo->msgid,$eo->msg) }}</li>
@endforeach @endforeach
</ul> </ul>
</td> </td>
</tr> </tr>
@endforeach @endforeach
</tbody> </tbody>
</table> </table>
<button type="submit" name="submit" class="btn btn-success float-end">Merge</button> <button type="submit" name="submit" class="btn btn-success float-end">Merge</button>
</div> </form>
</div> </div>
</form>
@include('widgets.error') @include('error')
</div>
@endsection @endsection

View File

@ -11,9 +11,9 @@
</div> </div>
</div> </div>
@includeWhen(session()->has('success'),'widgets.success',['msg'=>session()->get('success')]) @include('widgets.success')
<form class="needs-validation" method="post" novalidate> <form class="row g-0 needs-validation" method="post" novalidate>
@csrf @csrf
<div class="row pt-0"> <div class="row pt-0">

View File

@ -1,196 +1,199 @@
<form class="needs-validation" method="post" action="{{ url('system/address/add',$o->id) }}" novalidate> <form class="row g-0 needs-validation" method="post" action="{{ url('system/address/add',$o->id) }}" novalidate>
@csrf
<input type="hidden" id="action" name="action" value=""> <input type="hidden" id="action" name="action" value="">
@csrf
<div class="greyframe titledbox shadow0xb0"> <div class="row pt-0">
<h2 class="cap">Assign New/Update Existing Address</h2> <div class="col-12">
<div class="greyframe titledbox shadow0xb0">
<h2 class="cap">Assign New/Update Existing Address</h2>
<div class="row"> <div class="row">
<!-- Select Zone --> <!-- Select Zone -->
<div class="col-3"> <div class="col-3">
<label for="zone_id" class="form-label">Zone</label> <label for="zone_id" class="form-label">Zone</label>
<div class="input-group has-validation"> <div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-hash"></i></span> <span class="input-group-text"><i class="bi bi-hash"></i></span>
<select class="form-select @error('zone_id') is-invalid @enderror" id="zone_id" name="zone_id" required> <select class="form-select @error('zone_id') is-invalid @enderror" id="zone_id" name="zone_id" required>
<option></option> <option></option>
@foreach(\App\Models\Zone::active()->domainZoneOrder()->with(['domain'])->get() as $zo) @foreach(\App\Models\Zone::active()->domainZoneOrder()->with(['domain'])->get() as $zo)
<option value="{{ $zo->id }}">{{ $zo->zone_id }} <small>({{ $zo->domain->name }})</small></option> <option value="{{ $zo->id }}">{{ $zo->zone_id }} <small>({{ $zo->domain->name }})</small></option>
@endforeach @endforeach
</select> </select>
<span class="invalid-feedback" role="alert"> <span class="invalid-feedback" role="alert">
@error('zone_id') @error('zone_id')
{{ $message }} {{ $message }}
@else @else
Please select the Zone for the node's address. Please select the Zone for the node's address.
@enderror @enderror
</span> </span>
</div> </div>
</div> </div>
<!-- Select Region --> <!-- Select Region -->
<div class="col-3 d-none" id="region-select"> <div class="col-3 d-none" id="region-select">
<label for="region_id" class="form-label">Region</label> <label for="region_id" class="form-label">Region</label>
<div class="input-group has-validation"> <div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-geo"></i></span> <span class="input-group-text"><i class="bi bi-geo"></i></span>
<select class="form-select @error('region_id') is-invalid @enderror" id="region_id" name="region_id" required> <select class="form-select @error('region_id') is-invalid @enderror" id="region_id" name="region_id" required>
</select> </select>
<span class="invalid-feedback" role="alert"> <span class="invalid-feedback" role="alert">
@error('region_id') @error('region_id')
{{ $message }} {{ $message }}
@else @else
Please make a choice. Please make a choice.
@enderror @enderror
</span> </span>
</div> </div>
</div> </div>
<!-- Select Host --> <!-- Select Host -->
<div class="col-3 d-none" id="host-select"> <div class="col-3 d-none" id="host-select">
<label for="host_id" class="form-label">Host</label> <label for="host_id" class="form-label">Host</label>
<div class="input-group has-validation"> <div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-diagram-3-fill"></i></span> <span class="input-group-text"><i class="bi bi-diagram-3-fill"></i></span>
<select class="form-select @error('host_id') is-invalid @enderror" id="host_id" name="host_id"> <select class="form-select @error('host_id') is-invalid @enderror" id="host_id" name="host_id">
</select> </select>
<span class="invalid-feedback" role="alert"> <span class="invalid-feedback" role="alert">
@error('host_id') @error('host_id')
{{ $message }} {{ $message }}
@enderror @enderror
</span> </span>
</div> </div>
</div> </div>
<!-- Select Hub --> <!-- Select Hub -->
<div class="col-3 d-none" id="hub-select"> <div class="col-3 d-none" id="hub-select">
<label for="hub_id" class="form-label">Hub</label> <label for="hub_id" class="form-label">Hub</label>
<div class="input-group has-validation"> <div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-diagram-2-fill"></i></span> <span class="input-group-text"><i class="bi bi-diagram-2-fill"></i></span>
<select class="form-select @error('hub_id') is-invalid @enderror" id="hub_id" name="hub_id"> <select class="form-select @error('hub_id') is-invalid @enderror" id="hub_id" name="hub_id">
</select> </select>
<span class="invalid-feedback" role="alert"> <span class="invalid-feedback" role="alert">
@error('hub_id') @error('hub_id')
{{ $message }} {{ $message }}
@enderror @enderror
</span> </span>
</div> </div>
</div>
</div>
<div class="row">
<!-- Node/Point address -->
<div class="col-3 d-none" id="node-address">
<label for="node_id" class="form-label">Node/Point Address</label>
<div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-hash"></i></span>
<input type="text" style="width: 35%;" class="form-control text-end @error('node_id') is-invalid @enderror" id="node_id" placeholder="Node" name="node_id" value="{{ old('node_id',$o->node_id) }}" @cannot('admin',$o)disabled @endcannot>
<span class="input-group-text p-0">.</span>
<input type="text" class="form-control @error('point_id') is-invalid @enderror" id="point_id" placeholder="0" name="point_id" value="{{ old('point_id',$o->point_id) ?: 0 }}" @cannot('admin',$o)disabled @endcannot style="padding-left: 0;">
<span class="invalid-feedback" role="alert">
@error('node_id')
{{ $message }}
@enderror
@error('point_id')
{{ $message }}
@enderror
</span>
</div>
</div>
<!-- Region Address -->
<div class="col-3 ps-0 d-none" id="region-address">
<label for="region_id_new" class="form-label">Region Address</label>
<div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-hash"></i></span>
<input type="text" style="width: 35%;" class="form-control @error('region_id_new') is-invalid @enderror" id="region_id_new" placeholder="Region #" name="region_id_new" value="{{ old('region_id_new') }}" @cannot('admin',$o)disabled @endcannot>
<span class="input-group-text">/0.0</span>
<span class="invalid-feedback" role="alert">
@error('region_id_new')
{{ $message }}
@else
The region number is required.
@enderror
</span>
</div>
</div>
<!-- Host Address -->
<div class="col-3 ps-0 d-none" id="host-address">
<label for="host_id_new" class="form-label">Host Address</label>
<div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-hash"></i></span>
<input type="text" class="form-control text-end @error('host_id_new') is-invalid @enderror" id="host_id_new" placeholder="Host #" name="host_id_new" value="{{ old('host_id_new') }}" @cannot('admin',$o)disabled @endcannot>
<span class="input-group-text p-0">/</span>
<input type="text" class="form-control @error('node_id_new') is-invalid @enderror" id="node_id_new" placeholder="Node #" name="node_id_new" value="{{ old('node_id_new') }}" @cannot('admin',$o)disabled @endcannot>
<span class="input-group-text">.0</span>
<span class="invalid-feedback" role="alert">
@error('host_id_new')
{{ $message }}
@else
The host address is required.
@enderror
@error('node_id_new')
{{ $message }}
@else
The node address is required.
@enderror
</span>
</div>
</div>
<!-- Hub Checkbox -->
<div class="col-2 d-none" id="hub-checkbox">
<label for="hub" class="form-label">Hub</label>
<div class="input-group">
<div class="btn-group" role="group">
<input type="radio" class="btn-check" name="hub" id="hub_yes" value="1" required @cannot('admin',$o)disabled @endcannot @if(old('hub',$o->hub))checked @endif>
<label class="btn btn-outline-success" for="hub_yes">Yes</label>
<input type="radio" class="btn-check btn-danger" name="hub" id="hub_no" value="0" required @cannot('admin',$o)disabled @endcannot @if(! old('hub',$o->hub))checked @endif>
<label class="btn btn-outline-danger" for="hub_no">No</label>
</div> </div>
</div> </div>
</div>
<!-- Security --> <div class="row">
<div class="col-2 d-none" id="sec-level"> <!-- Node/Point address -->
<label for="security" class="form-label">Security Level</label> <div class="col-3 d-none" id="node-address">
<div class="input-group has-validation"> <label for="node_id" class="form-label">Node/Point Address</label>
<span class="input-group-text"><i class="bi bi-file-lock"></i></span> <div class="input-group has-validation">
<input type="text" class="form-control text-end @error('security') is-invalid @enderror" id="security" placeholder="#" name="security" value="{{ old('security') }}" @cannot('admin',$o)disabled @endcannot> <span class="input-group-text"><i class="bi bi-hash"></i></span>
<span class="invalid-feedback" role="alert"> <input type="text" style="width: 35%;" class="form-control text-end @error('node_id') is-invalid @enderror" id="node_id" placeholder="Node" name="node_id" value="{{ old('node_id',$o->node_id) }}" @cannot('admin',$o)disabled @endcannot>
@error('security') <span class="input-group-text p-0">.</span>
{{ $message }} <input type="text" class="form-control @error('point_id') is-invalid @enderror" id="point_id" placeholder="0" name="point_id" value="{{ old('point_id',$o->point_id) ?: 0 }}" @cannot('admin',$o)disabled @endcannot style="padding-left: 0;">
@enderror <span class="invalid-feedback" role="alert">
@error('node_id')
{{ $message }}
@enderror
@error('point_id')
{{ $message }}
@enderror
</span>
</div>
</div>
<!-- Region Address -->
<div class="col-3 ps-0 d-none" id="region-address">
<label for="region_id_new" class="form-label">Region Address</label>
<div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-hash"></i></span>
<input type="text" style="width: 35%;" class="form-control @error('region_id_new') is-invalid @enderror" id="region_id_new" placeholder="Region #" name="region_id_new" value="{{ old('region_id_new') }}" @cannot('admin',$o)disabled @endcannot>
<span class="input-group-text">/0.0</span>
<span class="invalid-feedback" role="alert">
@error('region_id_new')
{{ $message }}
@else
The region number is required.
@enderror
</span>
</div>
</div>
<!-- Host Address -->
<div class="col-3 ps-0 d-none" id="host-address">
<label for="host_id_new" class="form-label">Host Address</label>
<div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-hash"></i></span>
<input type="text" class="form-control text-end @error('host_id_new') is-invalid @enderror" id="host_id_new" placeholder="Host #" name="host_id_new" value="{{ old('host_id_new') }}" @cannot('admin',$o)disabled @endcannot>
<span class="input-group-text p-0">/</span>
<input type="text" class="form-control @error('node_id_new') is-invalid @enderror" id="node_id_new" placeholder="Node #" name="node_id_new" value="{{ old('node_id_new') }}" @cannot('admin',$o)disabled @endcannot>
<span class="input-group-text">.0</span>
<span class="invalid-feedback" role="alert">
@error('host_id_new')
{{ $message }}
@else
The host address is required.
@enderror
@error('node_id_new')
{{ $message }}
@else
The node address is required.
@enderror
</span>
</div>
</div>
<!-- Hub Checkbox -->
<div class="col-2 d-none" id="hub-checkbox">
<label for="hub" class="form-label">Hub</label>
<div class="input-group">
<div class="btn-group" role="group">
<input type="radio" class="btn-check" name="hub" id="hub_yes" value="1" required @cannot('admin',$o)disabled @endcannot @if(old('hub',$o->hub))checked @endif>
<label class="btn btn-outline-success" for="hub_yes">Yes</label>
<input type="radio" class="btn-check btn-danger" name="hub" id="hub_no" value="0" required @cannot('admin',$o)disabled @endcannot @if(! old('hub',$o->hub))checked @endif>
<label class="btn btn-outline-danger" for="hub_no">No</label>
</div>
</div>
</div>
<!-- Security -->
<div class="col-2 d-none" id="sec-level">
<label for="security" class="form-label">Security Level</label>
<div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-file-lock"></i></span>
<input type="text" class="form-control text-end @error('security') is-invalid @enderror" id="security" placeholder="#" name="security" value="{{ old('security') }}" @cannot('admin',$o)disabled @endcannot>
<span class="invalid-feedback" role="alert">
@error('security')
{{ $message }}
@enderror
</span>
</div>
</div>
</div>
<div class="row">
<div class="col-2">
<a href="{{ url('system') }}" class="btn btn-danger">Cancel</a>
</div>
<span class="col-6 mt-auto mx-auto text-center align-bottom">
@if($errors->count())
<span class="btn btn-sm btn-danger" role="alert">
There were errors with the submission.
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</span>
@endif
</span> </span>
@can('admin',$o)
<div class="col-2">
<button type="submit" id="submit" name="submit" class="btn btn-success float-end">Add/Update</button>
</div>
@endcan
</div> </div>
</div> </div>
</div> </div>
<div class="row">
<div class="col-2">
<a href="{{ url('system') }}" class="btn btn-danger">Cancel</a>
</div>
<span class="col-6 mt-auto mx-auto text-center align-bottom">
@if($errors->count())
<span class="btn btn-sm btn-danger" role="alert">
There were errors with the submission.
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</span>
@endif
</span>
@can('admin',$o)
<div class="col-2">
<button type="submit" id="submit" name="submit" class="btn btn-success float-end">Add/Update</button>
</div>
@endcan
</div>
</div> </div>
</form> </form>
@section('page-scripts') @section('page-scripts')

View File

@ -3,7 +3,7 @@
->orderBy('zone_id') ->orderBy('zone_id')
->get())->count()) ->get())->count())
<form class="needs-validation" method="post" action="{{ url('system/echoarea',$o->id) }}" novalidate> <form class="row g-0 needs-validation" method="post" action="{{ url('system/echoarea',$o->id) }}" novalidate>
@csrf @csrf
<div class="row pt-0"> <div class="row pt-0">

View File

@ -3,7 +3,7 @@
->orderBy('zone_id') ->orderBy('zone_id')
->get())->count()) ->get())->count())
<form class="needs-validation" method="post" action="{{ url('system/filearea',$o->id) }}" novalidate> <form class="row g-0 needs-validation" method="post" action="{{ url('system/filearea',$o->id) }}" novalidate>
@csrf @csrf
<div class="row pt-0"> <div class="row pt-0">

View File

@ -4,7 +4,9 @@
->whereNotIn('id',$o->sessions->pluck('id')) ->whereNotIn('id',$o->sessions->pluck('id'))
->get())->count()) ->get())->count())
<form class="needs-validation" method="post" action="{{ url('system/session/add',$o->id) }}" novalidate> <hr>
<form class="row g-0 needs-validation" method="post" action="{{ url('system/session/add',$o->id) }}" novalidate>
@csrf @csrf
<div class="row pt-0"> <div class="row pt-0">

View File

@ -0,0 +1,14 @@
<form class="row g-0 needs-validation" method="post" novalidate>
@csrf
<input type="hidden" name="system_id" value="{{ $o->id }}">
<div class="row">
<div class="col-12">
<div class="greyframe titledbox shadow0xb0">
<h2 class="cap">@can('update',$o) @if($o->exists) Update @else Add @endif @endif System</h2>
@include('system.widget.form-system')
</div>
</div>
</div>
</form>

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 BBS Systems</h2> <h2>BBS Systems</h2>
<p>BBS Systems Send and Receive Echomail and Files.</p> <p>BBS Systems Send and Receive Echomail and Files.</p>
</div> </div>
</div> </div>

View File

@ -4,7 +4,7 @@
@endsection @endsection
@section('content') @section('content')
<div class="row"> <div class="row pt-0">
<div class="col-12"> <div class="col-12">
<h2>List of Connectable Systems</h2> <h2>List of Connectable Systems</h2>

View File

@ -5,19 +5,21 @@ Move Address
@endsection @endsection
@section('content') @section('content')
<form class="needs-validation" method="post" novalidate> <div class="row">
@csrf <div class="col-12">
<h1>{{ $o->system->name }} - {{ $o->ftn }}@if($o->system->setup)<sup class="success" style="text-shadow: 0 0; font-size: 50%; top: -1em;">*</sup>@endif</h1>
@if($o->system->setup)<sup class="success" style="float:right;top:-2em;">* This Host</sup>@endif
</div>
</div>
<div class="row"> <div class="row pt-0">
<div class="col-12"> <div class="col-12">
<h1> <!-- @todo The list of presented system should only be those that the user can see -->
{{ $o->system->name }} - {{ $o->ftn }}@if($o->system->setup)<sup class="success">*</sup>@endif <div class="greyframe titledbox shadow0xb0">
@if($o->system->setup)<small class="success float-end">* This Host</small>@endif <h2 class="cap">Move Address</h2>
</h1>
<!-- @todo The list of presented system should only be those that the user can see --> <form class="row g-0 needs-validation" method="post" novalidate>
<div class="greyframe titledbox shadow0xb0"> @csrf
<h2 class="cap">Move Address</h2>
<div class="row"> <div class="row">
<!-- Choose System --> <!-- Choose System -->
@ -103,10 +105,10 @@ Move Address
</div> </div>
@endcan @endcan
</div> </div>
</div> </form>
</div> </div>
</div> </div>
</form> </div>
@endsection @endsection
@section('page-css') @section('page-css')

View File

@ -1,14 +1,452 @@
<form class="needs-validation" method="post" novalidate> <!-- $o = System::class -->
@csrf <div class="row pt-0">
<input type="hidden" name="system_id" value="{{ $o->id }}"> <div class="col-12">
<h4 class="mb-0 pb-2">System Users</h4>
<div class="row pt-0"> <div class="row pt-0">
<div class="col-12"> <!-- Users -->
<div class="greyframe titledbox shadow0xb0"> <div class="col-4">
<h2 class="cap">@can('update',$o) @if($o->exists) Update @else Add @endif @endif System</h2> <label for="users" class="form-label">Owners</label>
<div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-people-fill"></i></span>
<select style="width: 80%;" class="form-select @error('users') is-invalid @enderror" id="users" name="users[]">
<option value="">&nbsp;</option>
@foreach (\App\Models\User::orderBy('name')->active()->get() as $uo)
<option value="{{ $uo->id }}" @if(in_array($uo->id,old('users',$o->users->pluck('id')->toArray())))selected @endif>{{ $uo->name }} <small>({{ $uo->email }})</small></option>
@endforeach
</select>
@include('system.widget.system') <span class="invalid-feedback" role="alert">
@error('users')
{{ $message }}
@enderror
</span>
</div>
</div> </div>
</div> </div>
</div> </div>
</form> </div>
<div class="row">
<div class="col-12">
<h4 class="mb-0 pb-2">System Details</h4>
<div class="row pt-0">
<!-- Name -->
<div class="col-4">
<label for="name" class="form-label">BBS Name</label>
<div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-pc"></i></span>
<input type="text" class="form-control @error('name') is-invalid @enderror" id="name" placeholder="Name" name="name" value="{{ old('name',$o->name) }}" required @cannot('update',$o)readonly @endcannot autofocus>
<span id="search-icon" style="width: 0;"><i style="border-radius: 50%;" class="spinner-border spinner-border-sm text-dark d-none"></i></span>
<div id="system_search_results"></div>
<span class="invalid-feedback" role="alert">
@error('name')
{{ $message }}
@else
A name is required.
@enderror
</span>
</div>
</div>
<!-- ZeroTier ID -->
<div class="col-3">
<label for="zt_id" class="form-label">ZeroTier ID</label>
<div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-shield-lock-fill"></i></span>
<input type="text" class="form-control @error('zt_id') is-invalid @enderror" id="zt_id" placeholder="ZeroTier" name="zt_id" value="{{ old('zt_id',$o->zt_id) }}" @cannot($action,$o)readonly @endcannot>
<span class="invalid-feedback" role="alert">
@error('zt_id')
{{ $message }}
@enderror
</span>
</div>
</div>
<!-- Active -->
<div class="offset-2 col-2">
@can('update',$o)
<label for="active" class="form-label">Active</label>
<div class="input-group">
<div class="btn-group" role="group">
<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>
<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>
</div>
</div>
@endcan
</div>
</div>
<div class="row">
<!-- Sysop -->
<div class="col-4">
<label for="sysop" class="form-label">Sysop</label>
<div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-person-fill"></i></span>
<input type="text" class="form-control @error('sysop') is-invalid @enderror" id="sysop" placeholder="Sysop" name="sysop" value="{{ old('sysop',$o->sysop) }}" required @cannot('admin',$o)readonly @endcannot autocomplete="name">
<span class="invalid-feedback" role="alert">
@error('sysop')
{{ $message }}
@else
A Sysop's name is required.
@enderror
</span>
</div>
</div>
<!-- Location -->
<div class="col-4">
<label for="location" class="form-label">Location</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('location') is-invalid @enderror" id="location" placeholder="Location" name="location" value="{{ old('location',$o->location) }}" required @cannot($action,$o)readonly @endcannot>
<span class="invalid-feedback" role="alert">
@error('location')
{{ $message }}
@else
System location is required.
@enderror
</span>
</div>
</div>
<!-- Hold -->
<div class="offset-1 col-2">
@can('update',$o)
<label for="hold" class="form-label">Hold Mail <i class="bi bi-info-circle" title="Dont give the node any mail regardless of poll mode"></i></label>
<div class="input-group">
<div class="btn-group" role="group">
<input type="radio" class="btn-check" name="hold" id="hold_yes" value="1" required @if(old('hold',$o->hold))checked @endif>
<label class="btn btn-outline-warning" for="hold_yes">Yes</label>
<input type="radio" class="btn-check btn-danger" name="hold" id="hold_no" value="0" required @if(! old('hold',$o->hold))checked @endif>
<label class="btn btn-outline-success" for="hold_no">No</label>
</div>
</div>
@endcan
</div>
</div>
<div class="row">
<!-- Address -->
<div class="col-5">
<label for="address" class="form-label">BBS Internet Hostname</label>
<div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-globe"></i></span>
<input type="text" class="w-75 form-control @error('address') is-invalid @enderror" id="address" placeholder="FQDN" name="address" value="{{ old('address',$o->address) }}" @cannot($action,$o)readonly @endcannot>
<span class="invalid-feedback" role="alert">
@error('address')
{{ $message }}
@enderror
</span>
</div>
</div>
<!-- Phone -->
<div class="col-3">
<label for="phone" class="form-label">Phone</label>
<div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-telephone-fill"></i></span>
<input type="text" class="form-control @error('phone') is-invalid @enderror" id="phone" placeholder="Phone" name="phone" value="{{ old('phone',$o->phone) }}" @cannot($action,$o)readonly @endcannot>
<span class="invalid-feedback" role="alert">
@error('phone')
{{ $message }}
@enderror
</span>
</div>
</div>
<!-- Poll Mode -->
<div class="offset-1 col-3">
@can('update',$o)
<label for="pollmode" class="form-label">Poll Mode <i class="bi bi-info-circle" title="Poll node when mail available, poll on a schedule or hold mail for collection"></i></label>
<div class="input-group has-validation">
<div class="btn-group @error('pollmode') is-invalid @enderror" role="group">
<input type="radio" class="btn-check" name="pollmode" id="poll_crash" value="2" @if((int)old('pollmode',($o->pollmode === TRUE) ? 2 : 0) === 2)checked @endif>
<label class="btn btn-outline-success" for="poll_crash">Crash</label>
<input type="radio" class="btn-check btn-danger" name="pollmode" id="poll_normal" value="1" @if((int)old('pollmode',($o->pollmode === FALSE) ? 1 : 0) === 1)checked @endif>
<label class="btn btn-outline-secondary" for="poll_normal">Normal</label>
<input type="radio" class="btn-check btn-danger" name="pollmode" id="poll_hold" value="0" @if((int)old('pollmode',is_null($o->pollmode) ? 0 : 1) === 0)checked @endif>
<label class="btn btn-outline-warning" for="poll_hold">Hold</label>
</div>
<span class="invalid-feedback" role="alert">
@error('pollmode')
{{ $message }}
@enderror
</span>
</div>
@endcan
</div>
</div>
</div>
</div>
<div class="row">
<!-- Mailer Details -->
<div class="col-12">
<h4 class="pt-4 mb-0 pb-2">Mailer Details</h4>
<!-- Mailer Ports -->
<div class="pt-0 row">
<div class="col-3">
@foreach (\App\Models\Mailer::all() as $mo)
@php($x=$o->mailers->find($mo))
<div class="pt-0 row">
<div class="col-12">
<label for="mailer_port_{{ $mo->id }}" class="form-label w-100">{{ $mo->name }} <span class="float-end text-warning">{{ $x?->pivot->last_poll }}</span></label>
<div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-modem-fill"></i></span>
<input type="text" class="form-control text-end @error('mailer_details.'.$mo->id.'.port') is-invalid @enderror" id="mailer_port_{{ $mo->id }}" placeholder="Port" name="mailer_details[{{ $mo->id }}][port]" value="{{ old('mailer_details.'.$mo->id.'.port',$x?->pivot->port) }}" @cannot($action,$o)readonly @endcannot>
<div class="input-group-text">
<input type="checkbox" class="form-control-input" name="mailer_details[{{ $mo->id }}][active]" value="1" title="Active" @if(old('mailer_details.'.$mo->id.'.active',$x?->pivot->active))checked @endif>
</div>
<span class="invalid-feedback" role="alert">
@error('mailer_details.'.$mo->id.'.port')
{{ $message }}
@enderror
</span>
</div>
</div>
</div>
@endforeach
</div>
<!-- Mail Packet -->
<div class="col-2">
<label for="pkt_type" class="form-label">Mail Packet</label>
<div class="input-group">
<span class="input-group-text"><i class="bi bi-ui-radios"></i></span>
<select class="form-select @error('pkt_type') is-invalid @enderror" id="pkt_type" name="pkt_type" @cannot($action,$o)readonly @endcannot>
@foreach (\App\Classes\FTN\Packet::PACKET_TYPES as $type => $class)
<option value="{{ $type }}" @if(old('pkt_type',$o->pkt_type ?: config('fido.packet_default')) === $type)selected @endif>{{ $type }}</option>
@endforeach
</select>
<span class="invalid-feedback" role="alert">
@error('pkt_type')
{{ $message }}
@enderror
</span>
</div>
</div>
<div class="offset-3 col-4 @if((old('pollmode') === "0") || is_null($o->pollmode))d-none @endif" id="heartbeat_option">
@can('admin',$o)
<div class="row p-0">
<div class="offset-3 col-6">
<label for="method" class="form-label">Heartbeat <i class="bi bi-info-circle" title="Attempt contact after last seen"></i></label>
<div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-hourglass-bottom"></i></span>
<input type="text" class="form-control text-end @error('heartbeat') is-invalid @enderror" id="heartbeat" placeholder="Hours" name="heartbeat" value="{{ old('heartbeat',$o->heartbeat) }}">
<span class="invalid-feedback" role="alert">
@error('heartbeat')
{{ $message }}
@enderror
</span>
</div>
</div>
</div>
@endcan
@if (! is_null($o->pollmode))
<div class="row">
<div class="offset-3 col-9 bg-secondary rounded p-2 small">
@if($job = $o->poll())
<div class="row p-0">
<div class="col-4 text-dark">
@if($job->attempts)Last: @else Scheduled: @endif
</div>
<div class="col-8">
<strong class="highlight">{{ $job->created_at }}</strong>
</div>
</div>
<div class="row">
<div class="col-4 text-dark">
Attempts:
</div>
<div class="col-8">
<strong class="highlight">{{ $job->attempts ?: 0 }}</strong>
</div>
</div>
@if ($job->attempts)
<div class="row">
<div class="col-4 text-dark">
Next:
</div>
<div class="col-8">
<strong class="highlight">{{ $job->available_at->diffForHumans(now(),$job->available_at->isFuture() ? \Carbon\CarbonInterface::DIFF_ABSOLUTE : \Carbon\CarbonInterface::DIFF_RELATIVE_TO_NOW) }}</strong>
</div>
</div>
@endif
@else
<div class="row p-0">
<div class="col-4 text-dark">
Last Poll:
</div>
<div class="col-8">
<strong class="highlight">{{ ($x=$o->logs->where('originate',TRUE)->last())?->created_at ?: 'Never' }}</strong>
</div>
</div>
<div class="row">
<div class="col-4 text-dark">
Method:
</div>
<div class="col-8">
<strong class="highlight">{{ $x ? $x->mailer->name : '-' }}</strong>
</div>
</div>
@if ($o->heartbeat)
<div class="row">
<div class="col-4 text-dark">
Next Heartbeat:
</div>
<div class="col-8">
<strong class="highlight">{{ $x ? $x->created_at->addHours($o->heartbeat) : Carbon::now() }}</strong>
</div>
</div>
@endif
@endif
<div class="row">
<div class="col-4 text-dark">
Status:
</div>
<div class="col-8">
<strong class="highlight">
@if ($job) Queued
@elseif ($o->autohold)Auto Hold
@else
@switch($o->pollmode)
@case(TRUE) Crash @break;
@case(FALSE) Normal @break;
@default Hold
@endswitch
@endif
</strong>
</div>
</div>
</div>
</div>
{{--
<div class="col-12">
<table class="table monotable m-0 p-0 small noborder">
<tbody xstyle="border-style:dotted;">
<tr>
<td class="cap text-end">Status :</td>
<td>
@if ($job) Queued
@elseif ($o->autohold)Auto Hold
@else
@switch($o->pollmode)
@case(TRUE) Crash @break;
@case(FALSE) Normal @break;
@default Hold
@endswitch
@endif
</td>
</tr>
</tbody>
</table>
</div>
--}}
@endif
</div>
</div>
</div>
</div>
<div class="row">
<!-- BBS Details -->
<div class="col-12">
<h4 class="pt-4 mb-0 pb-2">BBS Details</h4>
<div class="pt-0 row">
<div class="col-2">
<label for="method" class="form-label">Connection Method</label>
<div class="input-group">
<span class="input-group-text"><i class="bi bi-wifi"></i></span>
<select class="form-select @error('method') is-invalid @enderror" id="method" name="method" @cannot($action,$o)readonly @endcannot>
<option></option>
<option value="23" @if(old('method',$o->method) == 23)selected @endif>Telnet</option>
<option value="22" @if(old('method',$o->method) == 22)selected @endif>SSH</option>
<option value="519" @if(old('method',$o->method) == 519)selected @endif>Rlogin</option>
</select>
</div>
</div>
<div class="col-2">
<label for="method" class="form-label">Port</label>
<div class="input-group">
<span class="input-group-text"><i class="bi bi-wifi"></i></span>
<input type="text" class="form-control text-end @error('port') is-invalid @enderror" id="port" placeholder="Port" name="port" value="{{ old('port',$o->port) }}" @cannot($action,$o)readonly @endcannot>
</div>
</div>
</div>
</div>
</div>
@can('admin',$o)
<div class="row">
<!-- Notes -->
<div class="col-12">
<label for="notes" class="form-label">Notes</label>
<textarea class="form-control" rows=3 name="notes" placeholder="Notes...">{{ old('notes',$o->notes) }}</textarea>
</div>
</div>
@endcan
<div class="row">
<div class="col-12">
@if($o->exists)
@can($action,$o)
<a href="{{ url('system') }}" class="btn btn-danger">Cancel</a>
<button type="submit" name="submit" class="btn btn-success float-end">@if ($o->exists)Save @else Add @endif</button>
@else
<input type="hidden" name="system_id" value="{{ $o->id }}">
<span><small><strong>NOTE:</strong> You'll be able to update these details after registration is completed.</small></span>
<button type="submit" class="btn btn-success float-end" name="submit" value="register">Register</button>
@endcan
@else
<button type="submit" class="btn btn-success float-end" name="submit" value="create">Register</button>
@endif
</div>
</div>
@section('page-css')
@css('select2')
@append
@section('page-scripts')
@js('select2')
<script type="text/javascript">
$(document).ready(function() {
$('#users').select2({
@cannot('admin')disabled: true @endcannot
/*multiple: true*/
});
$('#poll_normal').on('click',function() {
$('#heartbeat_option').removeClass('d-none');
})
$('#poll_crash').on('click',function() {
$('#heartbeat_option').removeClass('d-none');
})
$('#poll_hold').on('click',function() {
$('#heartbeat_option').addClass('d-none');
console.log('hold');
})
})
</script>
@append

View File

@ -1,441 +0,0 @@
<!-- $o = System::class -->
<div class="row">
<div class="col-xl-9 col-12">
<div class="row pt-0">
<div class="col-12">
<h4 class="mb-0 pb-2">System Users</h4>
<div class="row pt-0">
<!-- Users -->
<div class="col-6">
<label for="users" class="form-label">Owners</label>
<div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-people-fill"></i></span>
<select style="width: 80%;" class="form-select @error('users') is-invalid @enderror" id="users" name="users[]">
<option value="">&nbsp;</option>
@foreach (\App\Models\User::orderBy('name')->active()->get() as $uo)
<option value="{{ $uo->id }}" @if(in_array($uo->id,old('users',$o->users->pluck('id')->toArray())))selected @endif>{{ $uo->name }} <small>({{ $uo->email }})</small></option>
@endforeach
</select>
<span class="invalid-feedback" role="alert">
@error('users')
{{ $message }}
@enderror
</span>
</div>
</div>
</div>
</div>
</div>
<div class="row pt-4">
<div class="col-12">
<h4 class="mb-0 pb-2">System Details</h4>
<div class="row pt-0">
<!-- Name -->
<div class="col-7">
<label for="name" class="form-label">BBS Name</label>
<div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-pc"></i></span>
<input type="text" class="form-control @error('name') is-invalid @enderror" id="name" placeholder="Name" name="name" value="{{ old('name',$o->name) }}" required @cannot('update',$o)readonly @endcannot autofocus>
<span id="search-icon" style="width: 0;"><i style="border-radius: 50%;" class="spinner-border spinner-border-sm text-dark d-none"></i></span>
<div id="system_search_results"></div>
<span class="invalid-feedback" role="alert">
@error('name')
{{ $message }}
@else
A name is required.
@enderror
</span>
</div>
</div>
<!-- ZeroTier ID -->
<div class="col-5">
<label for="zt_id" class="form-label">ZeroTier ID</label>
<div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-shield-lock-fill"></i></span>
<input type="text" class="form-control @error('zt_id') is-invalid @enderror" id="zt_id" placeholder="ZeroTier" name="zt_id" value="{{ old('zt_id',$o->zt_id) }}" @cannot($action,$o)readonly @endcannot>
<span class="invalid-feedback" role="alert">
@error('zt_id')
{{ $message }}
@enderror
</span>
</div>
</div>
</div>
<div class="row">
<!-- Sysop -->
<div class="col-6">
<label for="sysop" class="form-label">Sysop</label>
<div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-person-fill"></i></span>
<input type="text" class="form-control @error('sysop') is-invalid @enderror" id="sysop" placeholder="Sysop" name="sysop" value="{{ old('sysop',$o->sysop) }}" required @cannot('admin',$o)readonly @endcannot autocomplete="name">
<span class="invalid-feedback" role="alert">
@error('sysop')
{{ $message }}
@else
A Sysop's name is required.
@enderror
</span>
</div>
</div>
<!-- Location -->
<div class="col-6">
<label for="location" class="form-label">Location</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('location') is-invalid @enderror" id="location" placeholder="Location" name="location" value="{{ old('location',$o->location) }}" required @cannot($action,$o)readonly @endcannot>
<span class="invalid-feedback" role="alert">
@error('location')
{{ $message }}
@else
System location is required.
@enderror
</span>
</div>
</div>
</div>
<div class="row">
<!-- Address -->
<div class="col-6">
<label for="address" class="form-label">BBS Internet Hostname</label>
<div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-globe"></i></span>
<input type="text" class="w-75 form-control @error('address') is-invalid @enderror" id="address" placeholder="FQDN" name="address" value="{{ old('address',$o->address) }}" @cannot($action,$o)readonly @endcannot>
<span class="invalid-feedback" role="alert">
@error('address')
{{ $message }}
@enderror
</span>
</div>
</div>
<!-- Phone -->
<div class="col-4">
<label for="phone" class="form-label">Phone</label>
<div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-telephone-fill"></i></span>
<input type="text" class="form-control @error('phone') is-invalid @enderror" id="phone" placeholder="Phone" name="phone" value="{{ old('phone',$o->phone) }}" @cannot($action,$o)readonly @endcannot>
<span class="invalid-feedback" role="alert">
@error('phone')
{{ $message }}
@enderror
</span>
</div>
</div>
</div>
</div>
</div>
<div class="row pt-4">
<!-- Mailer Details -->
<div class="col-12">
<h4 class="mb-0 pb-2">Mailer Details</h4>
<!-- Mailer Ports -->
<div class="row pt-0">
<div class="col-3">
@foreach (\App\Models\Mailer::all() as $mo)
@php($x=$o->mailers->find($mo))
<div class="row pt-0">
<div class="col-12">
<label for="mailer_port_{{ $mo->id }}" class="form-label w-100">{{ $mo->name }} <span class="float-end text-warning">{{ $x?->pivot->last_poll }}</span></label>
<div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-modem-fill"></i></span>
<input type="text" class="form-control text-end @error('mailer_details.'.$mo->id.'.port') is-invalid @enderror" id="mailer_port_{{ $mo->id }}" placeholder="Port" name="mailer_details[{{ $mo->id }}][port]" value="{{ old('mailer_details.'.$mo->id.'.port',$x?->pivot->port) }}" @cannot($action,$o)readonly @endcannot>
<div class="input-group-text">
<input type="checkbox" class="form-control-input" name="mailer_details[{{ $mo->id }}][active]" value="1" title="Active" @if(old('mailer_details.'.$mo->id.'.active',$x?->pivot->active))checked @endif>
</div>
<span class="invalid-feedback" role="alert">
@error('mailer_details.'.$mo->id.'.port')
{{ $message }}
@enderror
</span>
</div>
</div>
</div>
@endforeach
</div>
<!-- Mail Packet -->
<div class="col-4">
<label for="pkt_type" class="form-label">Mail Packet</label>
<div class="input-group">
<span class="input-group-text"><i class="bi bi-ui-radios"></i></span>
<select class="form-select @error('pkt_type') is-invalid @enderror" id="pkt_type" name="pkt_type" @cannot($action,$o)readonly @endcannot>
@foreach (\App\Classes\FTN\Packet::PACKET_TYPES as $type => $class)
<option value="{{ $type }}" @if(old('pkt_type',$o->pkt_type ?: config('fido.packet_default')) === $type)selected @endif>{{ $type }}</option>
@endforeach
</select>
<span class="invalid-feedback" role="alert">
@error('pkt_type')
{{ $message }}
@enderror
</span>
</div>
</div>
</div>
</div>
</div>
<div class="row pt-4">
<!-- BBS Details -->
<div class="col-12">
<h4 class="mb-0 pb-2">BBS Details</h4>
<div class="row pt-0">
<div class="col-4">
<label for="method" class="form-label">Connection Method</label>
<div class="input-group">
<span class="input-group-text"><i class="bi bi-wifi"></i></span>
<select class="form-select @error('method') is-invalid @enderror" id="method" name="method" @cannot($action,$o)readonly @endcannot>
<option></option>
<option value="23" @if(old('method',$o->method) == 23)selected @endif>Telnet</option>
<option value="22" @if(old('method',$o->method) == 22)selected @endif>SSH</option>
<option value="519" @if(old('method',$o->method) == 519)selected @endif>Rlogin</option>
</select>
</div>
</div>
<div class="col-3">
<label for="method" class="form-label">Port</label>
<div class="input-group">
<span class="input-group-text"><i class="bi bi-wifi"></i></span>
<input type="text" class="form-control text-end @error('port') is-invalid @enderror" id="port" placeholder="Port" name="port" value="{{ old('port',$o->port) }}" @cannot($action,$o)readonly @endcannot>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="col-xl-3 col-12">
<div class="row">
<!-- Active -->
<div class="col-6">
@can('update',$o)
<label for="active" class="form-label">Active</label>
<div class="input-group">
<div class="btn-group" role="group">
<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>
<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>
</div>
</div>
@endcan
</div>
</div>
<div class="row">
<!-- Hold -->
<div class="col-6">
@can('update',$o)
<label for="hold" class="form-label">Hold Mail <i class="bi bi-info-circle" title="Dont give the node any mail regardless of poll mode"></i></label>
<div class="input-group">
<div class="btn-group" role="group">
<input type="radio" class="btn-check" name="hold" id="hold_yes" value="1" required @if(old('hold',$o->hold))checked @endif>
<label class="btn btn-outline-warning" for="hold_yes">Yes</label>
<input type="radio" class="btn-check btn-danger" name="hold" id="hold_no" value="0" required @if(! old('hold',$o->hold))checked @endif>
<label class="btn btn-outline-success" for="hold_no">No</label>
</div>
</div>
@endcan
</div>
</div>
<div class="row">
<!-- Poll Mode -->
<div class="col-12">
@can('update',$o)
<label for="pollmode" class="form-label">Poll Mode <i class="bi bi-info-circle" title="Poll node when mail available, poll on a schedule or hold mail for collection"></i></label>
<div class="input-group has-validation">
<div class="btn-group @error('pollmode') is-invalid @enderror" role="group">
<input type="radio" class="btn-check" name="pollmode" id="poll_crash" value="2" @if((int)old('pollmode',($o->pollmode === TRUE) ? 2 : 0) === 2)checked @endif>
<label class="btn btn-outline-success" for="poll_crash">Crash</label>
<input type="radio" class="btn-check btn-danger" name="pollmode" id="poll_normal" value="1" @if((int)old('pollmode',($o->pollmode === FALSE) ? 1 : 0) === 1)checked @endif>
<label class="btn btn-outline-secondary" for="poll_normal">Normal</label>
<input type="radio" class="btn-check btn-danger" name="pollmode" id="poll_hold" value="0" @if((int)old('pollmode',is_null($o->pollmode) ? 0 : 1) === 0)checked @endif>
<label class="btn btn-outline-warning" for="poll_hold">Hold</label>
</div>
<span class="invalid-feedback" role="alert">
@error('pollmode')
{{ $message }}
@enderror
</span>
</div>
@endcan
</div>
</div>
<div class="row">
<div class="col-12 @if((old('pollmode') === "0") || is_null($o->pollmode))d-none @endif" id="heartbeat_option">
@can('admin',$o)
<div class="row p-0">
<div class="col-6">
<label for="heartbeat" class="form-label">Heartbeat <i class="bi bi-info-circle" title="Attempt contact after last seen"></i></label>
<div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-hourglass-bottom"></i></span>
<input type="text" class="form-control text-end @error('heartbeat') is-invalid @enderror" id="heartbeat" placeholder="Hrs" name="heartbeat" value="{{ old('heartbeat',$o->heartbeat) }}">
<span class="invalid-feedback" role="alert">
@error('heartbeat')
{{ $message }}
@enderror
</span>
</div>
</div>
</div>
@endcan
@if (! is_null($o->pollmode))
<div class="row">
<div class="col-12 bg-secondary rounded p-2 small">
@if($job = $o->poll())
<div class="row p-0">
<div class="col-4 text-dark">
@if($job->attempts)Last: @else Scheduled: @endif
</div>
<div class="col-8">
<strong class="highlight">{{ $job->created_at }}</strong>
</div>
</div>
<div class="row">
<div class="col-4 text-dark">
Attempts:
</div>
<div class="col-8">
<strong class="highlight">{{ $job->attempts ?: 0 }}</strong>
</div>
</div>
@if ($job->attempts)
<div class="row">
<div class="col-4 text-dark">
Next:
</div>
<div class="col-8">
<strong class="highlight">{{ $job->available_at->diffForHumans(now(),$job->available_at->isFuture() ? \Carbon\CarbonInterface::DIFF_ABSOLUTE : \Carbon\CarbonInterface::DIFF_RELATIVE_TO_NOW) }}</strong>
</div>
</div>
@endif
@else
<div class="row p-0">
<div class="col-4 text-dark">
Last Poll:
</div>
<div class="col-8">
<strong class="highlight">{{ ($x=$o->logs->where('originate',TRUE)->last())?->created_at ?: 'Never' }}</strong>
</div>
</div>
<div class="row">
<div class="col-4 text-dark">
Method:
</div>
<div class="col-8">
<strong class="highlight">{{ $x ? $x->mailer->name : '-' }}</strong>
</div>
</div>
@if ($o->heartbeat)
<div class="row">
<div class="col-4 text-dark">
Next Heartbeat:
</div>
<div class="col-8">
<strong class="highlight">{{ $x ? $x->created_at->addHours($o->heartbeat) : Carbon::now() }}</strong>
</div>
</div>
@endif
@endif
<div class="row">
<div class="col-4 text-dark">
Status:
</div>
<div class="col-8">
<strong class="highlight">
@if ($job) Queued
@elseif ($o->autohold)Auto Hold
@else
@switch($o->pollmode)
@case(TRUE) Crash @break;
@case(FALSE) Normal @break;
@default Hold
@endswitch
@endif
</strong>
</div>
</div>
</div>
</div>
@endif
</div>
</div>
</div>
</div>
@can('admin',$o)
<div class="row">
<!-- Notes -->
<div class="col-12">
<label for="notes" class="form-label">Notes</label>
<textarea class="form-control" rows=3 name="notes" placeholder="Notes...">{{ old('notes',$o->notes) }}</textarea>
</div>
</div>
@endcan
<div class="row">
<div class="col-12">
@if($o->exists)
@can($action,$o)
<a href="{{ url('system') }}" class="btn btn-danger">Cancel</a>
<button type="submit" name="submit" class="btn btn-success float-end">@if ($o->exists)Save @else Add @endif</button>
@else
<input type="hidden" name="system_id" value="{{ $o->id }}">
<span><small><strong>NOTE:</strong> You'll be able to update these details after registration is completed.</small></span>
<button type="submit" class="btn btn-success float-end" name="submit" value="register">Register</button>
@endcan
@else
<button type="submit" class="btn btn-success float-end" name="submit" value="create">Register</button>
@endif
</div>
</div>
@section('page-css')
@css('select2')
@append
@section('page-scripts')
@js('select2')
<script type="text/javascript">
$(document).ready(function() {
$('#users').select2({
@cannot('admin')disabled: true @endcannot
/*multiple: true*/
});
$('#poll_normal').on('click',function() {
$('#heartbeat_option').removeClass('d-none');
})
$('#poll_crash').on('click',function() {
$('#heartbeat_option').removeClass('d-none');
})
$('#poll_hold').on('click',function() {
$('#heartbeat_option').addClass('d-none');
console.log('hold');
})
})
</script>
@append

View File

@ -1,4 +1,3 @@
<!-- $o=User::class -->
@extends('layouts.app') @extends('layouts.app')
@section('htmlheader_title') @section('htmlheader_title')
@ -6,170 +5,135 @@
@endsection @endsection
@section('content') @section('content')
<form class="needs-validation" method="post" novalidate> <form class="row g-0 needs-validation" method="post" novalidate>
@csrf @csrf
<div class="row"> <div class="row">
<div class="col-12"> <div class="col-12">
@includeWhen(session()->has('success'),'widgets.success-row',['msg'=>session()->get('success')])
<div class="greyframe titledbox shadow0xb0"> <div class="greyframe titledbox shadow0xb0">
<h2 class="cap">@if($o->exists) Update @else Add @endif User</h2> <div class="row pt-0">
<div class="col-12">
<h2 class="cap">@if($o->exists) Update @else Add @endif User</h2>
<div class="row"> <div class="row">
<div class="col-4"> <div class="col-4">
<label for="name" class="form-label">Name</label> <label for="name" class="form-label">Name</label>
<div class="input-group has-validation"> <div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-tag-fill"></i></span> <span class="input-group-text"><i class="bi bi-tag-fill"></i></span>
<input type="text" class="form-control @error('name') is-invalid @enderror" id="name" placeholder="Name" name="name" value="{{ old('name',$o->name) }}" autocomplete="name" required @cannot('admin',$o)disabled @endcannot autofocus> <input type="text" class="form-control @error('name') is-invalid @enderror" id="name" placeholder="Name" name="name" value="{{ old('name',$o->name) }}" required @cannot('admin',$o)disabled @endcannot autofocus>
<span class="invalid-feedback" role="alert"> <span class="invalid-feedback" role="alert">
@error('name') @error('name')
{{ $message }} {{ $message }}
@else @else
A name is required. A name is required.
@enderror @enderror
</span> </span>
</div>
</div>
<div class="col-3">
<label for="alias" class="form-label">BBS Alias</label>
<div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-tag-fill"></i></span>
<input type="text" class="form-control @error('alias') is-invalid @enderror" id="alias" placeholder="alias" name="alias" value="{{ old('alias',$o->alias) }}" @cannot('admin',$o)disabled @endcannot>
<span class="invalid-feedback" role="alert">
@error('alias')
{{ $message }}
@enderror
</span>
</div>
</div>
<!-- Forward Netmail -->
<div class="col-4">
<label for="system_id" class="form-label">Forward Netmails</label>
<div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-envelope-at-fill"></i></span>
<select style="width: 80%;" class="form-select @error('system_id') is-invalid @enderror" id="system_id" name="system_id" required @cannot('admin',$o)disabled @endcannot>
<option value="">&nbsp;</option>
@foreach ($o->systems as $oo)
<option value="{{ $oo->id }}" @if(old('system_id',$o->system_id)==$oo->id)selected @endif>{{ $oo->name }}</option>
@endforeach
</select>
<span class="invalid-feedback" role="alert">
@error('system_id')
{{ $message }}
@enderror
</span>
</div>
</div>
</div> </div>
</div>
<div class="col-3"> <div class="row">
<label for="alias" class="form-label">BBS Alias</label> <div class="col-4">
<div class="input-group has-validation"> <label for="email" class="form-label">Email</label>
<span class="input-group-text"><i class="bi bi-tag-fill"></i></span> <div class="input-group has-validation">
<input type="text" class="form-control @error('alias') is-invalid @enderror" id="alias" placeholder="alias" name="alias" value="{{ old('alias',$o->alias) }}" @cannot('update',$o)disabled @endcannot> <span class="input-group-text"><i class="bi bi-person-badge"></i></span>
<span class="invalid-feedback" role="alert"> <input type="text" class="form-control @error('email') is-invalid @enderror" id="email" placeholder="Email" name="email" value="{{ old('email',$o->email) }}" required @cannot('admin',$o)disabled @endcannot>
@error('alias') <span class="invalid-feedback" role="alert">
{{ $message }} @error('email')
@enderror {{ $message }}
</span> @else
Email required for login.
@enderror
</span>
</div>
</div>
<div class="col-1">
<label for="active" class="form-label">Active</label>
<div class="input-group">
<div class="btn-group" role="group">
<input type="radio" class="btn-check" name="active" id="active_yes" value="1" required @cannot('admin',$o)disabled @endcannot @if(old('active',$o->active))checked @endif>
<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 @cannot('admin',$o)disabled @endcannot @if(! old('active',$o->active))checked @endif>
<label class="btn btn-outline-danger" for="active_no">No</label>
</div>
</div>
</div>
<div class="offset-1 col-1">
<label for="admin" class="form-label">Site Admin</label>
<div class="input-group">
<div class="btn-group" role="group" @if($user->id === $o->id)data-bs-toggle="tooltip" title="You cannot demote yourself" @endif>
<input type="radio" class="btn-check" name="admin" id="admin_yes" value="1" required @cannot('admin',$o)disabled @endcannot @if(old('admin',$o->admin))checked @endif>
<label class="btn btn-outline-success" for="admin_yes">Yes</label>
<input type="radio" class="btn-check btn-danger" name="admin" id="admin_no" value="0" required @if(($user->id === $o->id) || $user->cannot('admin',$o)) disabled @endif @if(! old('admin',$o->admin))checked @endif>
<label class="btn btn-outline-danger" for="admin_no">No</label>
</div>
</div>
</div>
</div> </div>
</div>
<!-- Forward Netmail --> <div class="row">
@can('admin',$o) <div class="col-12">
<div class="col-4"> <label for="pgp_pubkey" class="form-label">PGP Public Key</label>
<label for="system_id" class="form-label">Forward Netmails</label> <textarea class="form-control @error('pgp_pubkey')is-invalid @enderror" rows=3 name="pgp_pubkey" placeholder="PGP Public Key..." @cannot('admin',$o)disabled @endcannot>{{ old('pgp_pubkey',$o->pgp_pubkey) }}</textarea>
<div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-envelope-at-fill"></i></span>
<select style="width: 80%;" class="form-select @error('system_id') is-invalid @enderror" id="system_id" name="system_id" required>
<option value="">&nbsp;</option>
@foreach ($o->systems as $oo)
<option value="{{ $oo->id }}" @if(old('system_id',$o->system_id)==$oo->id)selected @endif>{{ $oo->name }}</option>
@endforeach
</select>
<span class="invalid-feedback" role="alert"> <span class="invalid-feedback" role="alert">
@error('system_id') @error('pgp_pubkey')
{{ $message }} {{ $message }}
@enderror @enderror
</span> </span>
</div> </div>
</div> </div>
@endcan
</div>
<div class="row"> <div class="row">
<div class="col-4"> <div class="col-12">
<label for="email" class="form-label">Email</label> <a href="{{ url('user') }}" class="btn btn-danger">Cancel</a>
<div class="input-group has-validation"> @can('admin',$o)
<span class="input-group-text"><i class="bi bi-person-badge"></i></span> <button type="submit" name="submit" class="btn btn-success float-end">@if ($o->exists)Save @else Add @endif</button>
<input type="text" class="form-control @error('email') is-invalid @enderror" id="email" placeholder="Email" name="email" value="{{ old('email',$o->email) }}" autocomplete="email" required @cannot('update',$o)disabled @endcannot> @endcan
<span class="invalid-feedback" role="alert">
@error('email')
{{ $message }}
@else
Email required for login.
@enderror
</span>
</div>
</div>
<div class="col-4">
<label for="password" class="form-label">Password</label>
<div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-person-badge"></i></span>
<input type="password" class="form-control @error('password') is-invalid @enderror" id="password" placeholder="{{ old('password',$o->password) ? 'Password Unchanged' : 'Password' }}" name="password" value="" @cannot('update',$o)disabled @endcannot>
<span class="invalid-feedback" role="alert">
@error('password')
{{ $message }}
@else
Password required for login.
@enderror
</span>
</div>
</div>
<div class="col-1">
@can('ownes',$o)
<label for="passkey" class="form-label">Passkey</label>
<div class="input-group has-validation">
<button class="btn {{ $o->passkey ? 'btn-primary' : 'btn-outline-primary' }}" id="passkey"><i class="bi bi-key"></i></button>
<span class="invalid-feedback" role="alert">
@error('passkey')
{{ $message }}
@enderror
</span>
</div>
@endcan
</div>
@can('admin',$o)
<div class="col-3">
<div class="row p-0">
<div class="col-xl-6 col-12">
<span class="form-label" style="font-size: 75%; margin-bottom: 1px;">Active</span>
<div class="input-group">
<div class="btn-group" role="group">
<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>
<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>
</div>
</div>
</div>
<div class="col-xl-6 col-12">
<span class="form-label" style="font-size: 75%; margin-bottom: 1px;">Site Admin</span>
<div class="input-group">
<div class="btn-group" role="group" @if($user->id === $o->id)data-bs-toggle="tooltip" title="You cannot demote yourself" @endif>
<input type="radio" class="btn-check" name="admin" id="admin_yes" value="1" required @if(old('admin',$o->admin))checked @endif>
<label class="btn btn-outline-success" for="admin_yes">Yes</label>
<input type="radio" class="btn-check btn-danger" name="admin" id="admin_no" value="0" required @if(($user->id === $o->id) || $user->cannot('admin',$o)) disabled @endif @if(! old('admin',$o->admin))checked @endif>
<label class="btn btn-outline-danger" for="admin_no">No</label>
</div>
</div>
</div>
</div> </div>
</div> </div>
@endcan
</div>
<div class="row">
<div class="col-12">
<label for="pgp_pubkey" class="form-label">PGP Public Key</label>
<textarea class="form-control @error('pgp_pubkey')is-invalid @enderror" rows=3 id="pgp_pubkey" name="pgp_pubkey" placeholder="PGP Public Key..." @cannot('update',$o)disabled @endcannot>{{ old('pgp_pubkey',$o->pgp_pubkey) }}</textarea>
<span class="invalid-feedback" role="alert">
@error('pgp_pubkey')
{{ $message }}
@enderror
</span>
</div>
</div>
<div class="row">
<div class="col-12">
<a href="{{ back()->getTargetUrl() }}" class="btn btn-danger">Cancel</a>
@canany(['admin','update'],$o)
<button type="submit" name="submit" class="btn btn-success float-end">@if ($o->exists)Save @else Add @endif</button>
@endcan
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="row"> <div class="row pt-5">
<div class="col-12"> <div class="col-12">
<h3>Systems</h3> <h3>Systems</h3>
@ -210,11 +174,8 @@
@section('page-scripts') @section('page-scripts')
@js('select2') @js('select2')
<!-- Passkeys -->
<script type='text/javascript' src='{{ asset('/passkey/passkey.js') }}'></script>
@if($user->id === $o->id) @if($user->id === $o->id)
<script type="text/javascript"> <script>
var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]')) var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'))
var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) { var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) {
return new bootstrap.Tooltip(tooltipTriggerEl) return new bootstrap.Tooltip(tooltipTriggerEl)
@ -225,37 +186,6 @@
<script type="text/javascript"> <script type="text/javascript">
$(document).ready(function() { $(document).ready(function() {
$('#system_id').select2(); $('#system_id').select2();
$('#passkey').on('click',function(item) {
if (passkey_debug)
console.log('Passkey: Create Click');
// Availability of `window.PublicKeyCredential` means WebAuthn is usable.
// `isUserVerifyingPlatformAuthenticatorAvailable` means the feature detection is usable.
// `sConditionalMediationAvailable` means the feature detection is usable.
if (window.PublicKeyCredential &&
PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable &&
PublicKeyCredential.isConditionalMediationAvailable) {
// Check if user verifying platform authenticator is available.
Promise.all([
PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable(),
PublicKeyCredential.isConditionalMediationAvailable(),
]).then(results => {
if (passkey_debug)
console.log('Passkey: Browser Supported');
if (results.every(r => r === true)) {
passkey_register('{{ csrf_token() }}',$(this),'bi-key','btn-primary','{{ $o->passkey ? 'btn-primary' : 'btn-outline-primary' }}');
} else {
alert('It seems that passkey is NOT supported by your browse (B)');
}
});
} else {
alert('It seems that passkey is NOT supported by your browser (A)');
}
return false;
});
}); });
</script> </script>
@append @append

View File

@ -5,10 +5,14 @@
@section('content') @section('content')
<div class="row"> <div class="row">
<div class="col-12"> <div class="row">
<h2>System Users</h2> <div class="col-12">
<h2>System Users</h2>
</div>
</div>
<p>This system is aware of the following users (you can <a href="{{ url('user/addedit') }}">add</a> more):</p> <div class="col-12">
<p>This system is aware of the following users @can('admin',(new \App\Models\User))(you can <a href="{{ url('user/addedit') }}">add</a> more)@endcan:</p>
<table class="table monotable" id="user"> <table class="table monotable" id="user">
<thead> <thead>
<tr> <tr>

View File

@ -4,70 +4,66 @@
@endsection @endsection
@section('content') @section('content')
<form class="needs-validation" method="post" novalidate> <form class="row g-0 needs-validation" method="post" novalidate>
@csrf @csrf
<input type="hidden" id="address_id" name="address_id"> <input type="hidden" id="address_id" name="address_id">
<div class="row"> <div class="greyframe titledbox shadow0xb0">
<div class="col-12"> <h2 class="cap">Enter your Link code</h2>
<div class="greyframe titledbox shadow0xb0">
<h2 class="cap">Enter your Link code</h2>
<!-- SYSTEM --> <!-- SYSTEM -->
<div class="row"> <div class="row">
<!-- Name --> <!-- Name -->
<div class="col-5"> <div class="col-5">
<label for="system" class="form-label">BBS Name</label> <label for="system" class="form-label">BBS Name</label>
<div class="input-group has-validation"> <div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-laptop-fill"></i></span> <span class="input-group-text"><i class="bi bi-laptop-fill"></i></span>
<select style="width: 80%;" class="form-select @error('system_id') is-invalid @enderror" id="system" name="address_id" required> <select style="width: 80%;" class="form-select @error('system_id') is-invalid @enderror" id="system" name="address_id" required>
<option value="">&nbsp;</option> <option value="">&nbsp;</option>
@foreach (\App\Models\Address::select(['addresses.id','addresses.host_id','addresses.node_id','addresses.point_id','addresses.zone_id','systems.name']) @foreach (\App\Models\Address::select(['addresses.id','addresses.host_id','addresses.node_id','addresses.point_id','addresses.zone_id','systems.name'])
->active() ->active()
->join('systems',['systems.id'=>'addresses.system_id']) ->join('systems',['systems.id'=>'addresses.system_id'])
->whereRaw('systems.id NOT IN (SELECT system_id FROM system_user)') ->whereRaw('systems.id NOT IN (SELECT system_id FROM system_user)')
->with(['zone']) ->with(['zone'])
->orderBy('systems.name') ->orderBy('systems.name')
->get() as $oo) ->get() as $oo)
<option value="{{ $oo->id }}" @if(old('id')===$oo->id)selected @endif>{{ $oo->name }} ({{ $oo->ftn3d }})</option> <option value="{{ $oo->id }}" @if(old('id')===$oo->id)selected @endif>{{ $oo->name }} ({{ $oo->ftn3d }})</option>
@endforeach @endforeach
</select> </select>
<span class="invalid-feedback" role="alert"> <span class="invalid-feedback" role="alert">
@error('system_id') @error('system_id')
{{ $message }} {{ $message }}
@else @else
BBS Name is required. BBS Name is required.
@enderror @enderror
</span> </span>
</div>
</div>
</div> </div>
</div>
</div>
<!-- CODE --> <!-- CODE -->
<div class="row"> <div class="row">
<div class="col-4"> <div class="col-4">
<label for="code" class="form-label">Code</label> <label for="code" class="form-label">Code</label>
<div class="input-group has-validation"> <div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-fingerprint"></i></span> <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> <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"> <span class="invalid-feedback" role="alert">
@error('code') @error('code')
{{ $message }} {{ $message }}
@else @else
A code is required. A code is required.
@enderror @enderror
</span> </span>
</div>
</div>
</div> </div>
</div>
</div>
<div class="row"> <div class="row">
<div class="col-12"> <div class="col-12">
<a href="{{ url('home') }}" class="btn btn-danger">Cancel</a> <a href="{{ url('home') }}" class="btn btn-danger">Cancel</a>
<button type="submit" name="submit" class="btn btn-success float-end">Validate</button> <button type="submit" name="submit" class="btn btn-success float-end">Validate</button>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -5,7 +5,7 @@
@endsection @endsection
@section('content') @section('content')
<form class="needs-validation" method="post" autocomplete="off" novalidate> <form class="row g-0 needs-validation" method="post" autocomplete="off" novalidate>
@csrf @csrf
<div class="row"> <div class="row">

View File

@ -27,14 +27,14 @@
<p>Otherwise, if all is good, we'll send a netmail to <strong class="highlight">{{ $o->sysop }}</strong> at <strong class="highlight">{{ $o->access_mailer }}</strong></p> with further details. <p>Otherwise, if all is good, we'll send a netmail to <strong class="highlight">{{ $o->sysop }}</strong> at <strong class="highlight">{{ $o->access_mailer }}</strong></p> with further details.
<form class="needs-validation" method="post" autocomplete="off" action="{{ url('user/system/link') }}" novalidate> <form class="row g-0 needs-validation" method="post" autocomplete="off" action="{{ url('user/system/link') }}" novalidate>
@csrf @csrf
<input type="hidden" name="system_id" value="{{ $o->id }}"> <input type="hidden" name="system_id" value="{{ $o->id }}">
<input type="hidden" name="name" value="{{ $o->name }}"> <input type="hidden" name="name" value="{{ $o->name }}">
<div class="row pb-2"> <div class="row">
<div class="col-12"> <div class="col-12 pb-2">
<input type="submit" name="action" class="btn btn-success" value="Link"> <input type="submit" name="action" class="btn btn-success" value="Link">
</div> </div>
</div> </div>

View File

@ -1,5 +0,0 @@
<div class="row">
<div class="col-8 m-auto">
@include('widgets.success')
</div>
</div>

View File

@ -1,5 +1,10 @@
<!-- Success --> <!-- Success -->
<div class="alert alert-success alert-dismissible fade show" role="alert"> @if(session()->has('success'))
<i class="bi bi-hand-thumbs-up"></i> {{ $msg }} <div class="alert alert-success alert-dismissible fade show" role="alert">
<button type="button" class="btn btn-sm btn-close" data-bs-dismiss="alert" aria-label="Close"></button> <h4 class="text-success"><i class="bi bi-hand-thumbs-up"></i> Success!</h4>
</div> <ul>
<li>{{ session()->get('success') }}</li>
</ul>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
@endif

View File

@ -5,7 +5,7 @@
@endsection @endsection
@section('content') @section('content')
<form class="needs-validation" method="post" novalidate> <form class="row g-0 needs-validation" method="post" novalidate>
@csrf @csrf
<div class="row"> <div class="row">

View File

@ -50,15 +50,10 @@ Route::view('system/list','system.list');
Route::get('system/view/{o}',[SystemController::class,'view']) Route::get('system/view/{o}',[SystemController::class,'view'])
->where('o','[0-9]+'); ->where('o','[0-9]+');
Route::get('search',[HomeController::class,'search']); Route::get('search',[HomeController::class,'search']);
Route::view('user/permissions','auth.permissions');
Route::middleware(['auth','verified','activeuser'])->group(function () { Route::middleware(['auth','verified','activeuser'])->group(function () {
Route::view('dashboard','dashboard'); Route::view('dashboard','dashboard');
/* ACCOUNT PATHS */
Route::match(['get','post'],'user/addedit/{o?}',[UserController::class,'add_edit'])
->where('o','[0-9]+');
/* DOMAIN PATHS */ /* DOMAIN PATHS */
Route::view('domain','domain.home'); Route::view('domain','domain.home');
Route::get('domain/api/hosts/{o}/{region}',[DomainController::class,'api_hosts']) Route::get('domain/api/hosts/{o}/{region}',[DomainController::class,'api_hosts'])
@ -126,6 +121,7 @@ Route::middleware(['auth','verified','activeuser'])->group(function () {
Route::post('packet/contents/{o}/{packet}',[HomeController::class,'packet_contents']) Route::post('packet/contents/{o}/{packet}',[HomeController::class,'packet_contents'])
->where('o','[0-9]+') ->where('o','[0-9]+')
->where('packet','[[:xdigit:]]+'); ->where('packet','[[:xdigit:]]+');
Route::get('permissions',[HomeController::class,'permissions']);
Route::match(['get','post'],'user/system/register',[SystemController::class,'register']); Route::match(['get','post'],'user/system/register',[SystemController::class,'register']);
Route::match(['post'],'user/system/link',[SystemController::class,'system_link']); Route::match(['post'],'user/system/link',[SystemController::class,'system_link']);
@ -147,5 +143,7 @@ Route::middleware(['auth','can:admin'])->group(function () {
Route::match(['get','post'],'address/merge/{id}',[SystemController::class,'address_merge']); Route::match(['get','post'],'address/merge/{id}',[SystemController::class,'address_merge']);
Route::match(['get','post'],'setup',[HomeController::class,'setup']); Route::match(['get','post'],'setup',[HomeController::class,'setup']);
Route::view('user/list','user.list'); Route::view('user','user.home');
Route::match(['get','post'],'user/addedit/{o?}',[UserController::class,'add_edit'])
->where('o','[0-9]+');
}); });