Update on security, user to edit their own system

This commit is contained in:
Deon George 2024-05-18 08:27:17 +10:00
parent 29710c37c2
commit 59ec5f5a0c
8 changed files with 85 additions and 39 deletions

View File

@ -3,7 +3,9 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use Carbon\Carbon; use Carbon\Carbon;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Database\QueryException; use Illuminate\Database\QueryException;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Arr; use Illuminate\Support\Arr;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
@ -14,7 +16,7 @@ use Illuminate\Support\Facades\Notification;
use Illuminate\Support\ViewErrorBag; use Illuminate\Support\ViewErrorBag;
use App\Classes\FTN\Message; use App\Classes\FTN\Message;
use App\Http\Requests\{AddressMerge,AreafixRequest,SystemRegister}; use App\Http\Requests\{AddressMerge,AreafixRequest,SystemRegister,SystemSessionRequest};
use App\Jobs\AddressPoll; use App\Jobs\AddressPoll;
use App\Models\{Address,Echoarea,Echomail,Filearea,Netmail,Setup,System,Zone}; use App\Models\{Address,Echoarea,Echomail,Filearea,Netmail,Setup,System,Zone};
use App\Notifications\Netmails\AddressLink; use App\Notifications\Netmails\AddressLink;
@ -29,8 +31,6 @@ class SystemController extends Controller
*/ */
public function add_edit(SystemRegister $request,System $o) public function add_edit(SystemRegister $request,System $o)
{ {
$this->authorize('update',$o);
if ($request->post()) { if ($request->post()) {
foreach (['name','location','sysop','hold','phone','address','port','active','method','notes','zt_id','pkt_type','heartbeat'] as $key) foreach (['name','location','sysop','hold','phone','address','port','active','method','notes','zt_id','pkt_type','heartbeat'] as $key)
$o->{$key} = $request->post($key); $o->{$key} = $request->post($key);
@ -836,26 +836,14 @@ class SystemController extends Controller
/** /**
* Add Session details * Add Session details
* *
* @param Request $request * @param SystemSessionRequest $request
* @param System $o * @param System $o
* @return \Illuminate\Http\RedirectResponse * @return \Illuminate\Http\RedirectResponse
* @throws \Illuminate\Auth\Access\AuthorizationException * @throws \Illuminate\Auth\Access\AuthorizationException
*/ */
public function session_add(Request $request,System $o) public function session_add(SystemSessionRequest $request,System $o)
{ {
// @todo This should be admin of the zone $zo = Zone::findOrFail($request->zone_id);
$this->authorize('update',$o);
session()->flash('accordion','session');
$validate = $request->validate([
'zone_id' => 'required|exists:zones,id',
'sespass' => 'required|string|min:4',
'pktpass' => 'required|string|min:4|max:8',
'ticpass' => 'required|string|min:4',
'fixpass' => 'required|string|min:4',
]);
$zo = Zone::findOrFail($validate['zone_id']);
/* /*
// @todo Disabling this, it needs improvement. If the new node is the ZC it becomes the default for the zone (and therefore remove all defaults from other addresses in the same zone), otherwise default should be false // @todo Disabling this, it needs improvement. If the new node is the ZC it becomes the default for the zone (and therefore remove all defaults from other addresses in the same zone), otherwise default should be false
@ -866,7 +854,7 @@ class SystemController extends Controller
} }
*/ */
$o->sessions()->attach($zo,$validate); $o->sessions()->attach($zo,$request->validated());
return redirect()->to(sprintf('system/addedit/%d',$o->id)); return redirect()->to(sprintf('system/addedit/%d',$o->id));
} }
@ -874,9 +862,10 @@ class SystemController extends Controller
/** /**
* Delete address assigned to a host * Delete address assigned to a host
* *
* @param Address $o * @param System $o
* @return \Illuminate\Http\RedirectResponse * @param Zone $zo
* @throws \Illuminate\Auth\Access\AuthorizationException * @return RedirectResponse
* @throws AuthorizationException
*/ */
public function session_del(System $o,Zone $zo) public function session_del(System $o,Zone $zo)
{ {

View File

@ -22,17 +22,14 @@ class SystemRegister extends FormRequest
*/ */
public function authorize(Request $request) public function authorize(Request $request)
{ {
$this->so = new System; if (! $request->post())
return TRUE;
if (is_numeric($request->name)) { // Cannot claim this site
$this->so = System::findOrNew($request->name); if ($this->route('o')->id === Setup::findOrFail(config('app.id'))->system_id)
return FALSE;
// Cannot claim this site return Gate::allows($this->route('o')->users->count() ? 'update_nn' : 'register',$this->route('o'));
if ($this->so->id === Setup::findOrFail(config('app.id'))->system_id)
return FALSE;
}
return Gate::allows(is_numeric($request->name) && $this->so->users->count() ? 'update' : 'register',$this->so);
} }
public function messages(): array public function messages(): array

View File

@ -0,0 +1,35 @@
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Gate;
class SystemSessionRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
session()->flash('accordion','session');
return Gate::allows('update_nn',$this->route('o'));
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
return [
'zone_id' => 'required|exists:zones,id',
'sespass' => 'required|string|min:4',
'pktpass' => 'required|string|min:4|max:8',
'ticpass' => 'required|string|min:4',
'fixpass' => 'required|string|min:4',
];
}
}

View File

@ -110,7 +110,8 @@ class System extends Model
public function sessions() public function sessions()
{ {
return $this->belongsToMany(Zone::class) return $this->belongsToMany(Zone::class)
->withPivot(['sespass','pktpass','ticpass','fixpass','zt_ipv4','zt_ipv6','default']); ->withPivot(['sespass','pktpass','ticpass','fixpass','zt_ipv4','zt_ipv6','default'])
->dontCache();
} }
/** /**

View File

@ -6,6 +6,21 @@ use Illuminate\Auth\Access\HandlesAuthorization;
use App\Models\{System,User}; use App\Models\{System,User};
/**
* This handles updating system records
*
* Authorisation is defined by function_role_only, where
* - function = create,delete,update
* - role = admin,zc,rc,nc,hc,nn,pt
* - only = only that role can do (no hierarchy permission)
* ie:
* - admin - only site admin can do (user = admin)
* - zc - only ZC can perform (user has an address that is a ZC)
* - rc - only RC (or ZC) ...
* - hc - only HC (or ZC/RC) ...
* - nn - only NN (or ZC/RC/HC) ...
* - pt - only PT (or ZC/RC/HC/NN) ...
*/
class SystemPolicy class SystemPolicy
{ {
use HandlesAuthorization; use HandlesAuthorization;
@ -49,7 +64,7 @@ class SystemPolicy
* @param System $system * @param System $system
* @return bool * @return bool
*/ */
public function update(User $user, System $system): bool public function update_nn(User $user,System $system): bool
{ {
// Site Admins can always edit // Site Admins can always edit
if ($user->isAdmin()) if ($user->isAdmin())
@ -59,7 +74,8 @@ class SystemPolicy
if (! $system->exists) if (! $system->exists)
return FALSE; return FALSE;
return $system->users->contains($user) // @todo Permit ZC, RC, NC, HUB user
&& (($system->addresses->count() === 0) || ($system->addresses->where('validated',TRUE)->count()));
return $system->users->contains($user) && $system->akas->count();
} }
} }

View File

@ -217,7 +217,9 @@
@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> @can('admin')
<span class="default" itemid="{{ $oo->id }}"><i class="bi bi-{{ $x->count() ? 'check-square' : 'square' }}"></i></span>
@endcan
@endif @endif
</td> </td>
<td>{{ $oo->pivot->sespass }}</td> <td>{{ $oo->pivot->sespass }}</td>
@ -603,6 +605,7 @@
@section('page-scripts') @section('page-scripts')
<script type="text/javascript"> <script type="text/javascript">
$(document).ready(function () { $(document).ready(function () {
@can('admin')
$('.default').click(function () { $('.default').click(function () {
var item = this; var item = this;
icon = $(item).find('i'); icon = $(item).find('i');
@ -634,6 +637,7 @@
cache: false cache: false
}) })
}); });
@endcan
$('data.validated').on('click',function(item) { $('data.validated').on('click',function(item) {
that = $(this); that = $(this);
var values = item.delegateTarget.value.split(':'); var values = item.delegateTarget.value.split(':');

View File

@ -42,7 +42,7 @@
<tbody> <tbody>
@foreach (\App\Models\System::active()->with(['addresses.zone.domain'])->get() as $oo) @foreach (\App\Models\System::active()->with(['addresses.zone.domain'])->get() as $oo)
<tr> <tr>
<td><a href="{{ url('system/addedit',[$oo->id]) }}" @cannot('update',$oo)class="disabled" @endcannot>{{ $oo->id }}</a></td> <td><a href="{{ url('system/addedit',[$oo->id]) }}" @cannot('update_nn',$oo)class="disabled" @endcannot>{{ $oo->id }}</a></td>
<td>{{ $oo->name }} @if(! $oo->active)<span class="float-end"><small>[i]</small></span>@endif</td> <td>{{ $oo->name }} @if(! $oo->active)<span class="float-end"><small>[i]</small></span>@endif</td>
<td>{{ $oo->sysop }}</td> <td>{{ $oo->sysop }}</td>
<td>{{ $oo->location }}</td> <td>{{ $oo->location }}</td>

View File

@ -1,6 +1,10 @@
<!-- $o = System::class --> <!-- $o = System::class -->
@if(($x=\App\Models\Zone::active() @php
->whereIn('id',$o->zones->pluck('id')) use App\Models\Zone;
@endphp
@if(($x=Zone::active()
->whereIn('id',$o->addresses->pluck('zone.id'))
->whereNotIn('id',$o->sessions->pluck('id')) ->whereNotIn('id',$o->sessions->pluck('id'))
->with(['domain']) ->with(['domain'])
->get())->count()) ->get())->count())