Added Passkey login, fixed password reset as a result of updating laravel

This commit is contained in:
2024-07-23 00:13:54 +10:00
parent b486a0eac4
commit c91a2fa8e5
15 changed files with 965 additions and 223 deletions

View File

@@ -0,0 +1,126 @@
@extends('adminlte::layouts.app')
@section('htmlheader_title')
{{ ($o??$user)->role }} Settings
@endsection
@section('page_title')
{{ ($o??$user)->name_full }}
@endsection
@section('contentheader_title')
{{ ($o??$user)->name_full }}
@endsection
@section('contentheader_description')
{{ ($o??$user)->role }}
@endsection
@use(App\Models\Country)
<!-- ($o??$user)=User::class -->
@section('main-content')
<div class="row">
<div class="col">
<div class="card">
<div class="card-header">
<div class="card-title">Update Settings</div>
@session('success')<x-leenooks::success class="float-right">{{ $value }}</x-leenooks::success>@endsession
</div>
<form method="POST" action="{{ url(request()->path(),[($o??$user)->id]) }}">
@csrf
<div class="card-body">
<div class="row">
<div class="col-12 col-sm-6">
<div class="row">
<div class="col">
<x-leenooks::form.email id="email" name="email" icon="fa-at" label="Email" :value="($o??$user)->email ?? ''"/>
</div>
</div>
<div class="row">
<div class="col">
<x-leenooks::form.password id="password" name="password" icon="fa-lock" label="Password"/>
</div>
</div>
<div class="row">
<div class="col">
<x-leenooks::form.password id="password_confirm" name="password_confirmation" icon="fa-lock" label="Password Confirm"/>
</div>
</div>
<div class="row">
<div class="col pb-3">
<button type="reset" id="passkey" name="passkey" @class(['btn','btn-success'=>$x=($o??$user)->passkey,'btn-outline-secondary'=>! $x])><i class="fas fa-fw fa-key"></i> Passkey</button>
</div>
</div>
</div>
<div class="col-12 col-sm-6">
<div class="row">
<div class="col-12 col-md-6">
<x-leenooks::form.text name="firstname" icon="fa-headset" label="First Name" :value="($o??$user)->firstname ?? ''"/>
</div>
<div class="col-12 col-md-6">
<x-leenooks::form.text name="lastname" icon="fa-signature" label="Last Name" :value="($o??$user)->lastname ?? ''"/>
</div>
</div>
<div class="row">
<div class="col">
<x-leenooks::form.text name="address1" icon="fa-map" label="Address" :value="($o??$user)->address1 ?? ''"/>
</div>
</div>
<div class="row">
<div class="col">
<x-leenooks::form.text name="address2" :value="($o??$user)->address2 ?? ''"/>
</div>
</div>
<div class="row">
<div class="col-12 col-md-4">
<x-leenooks::form.text name="city" label="City" :value="($o??$user)->city ?? ''"/>
</div>
<div class="col-12 col-md-4">
<x-leenooks::form.text name="state" label="State" :value="($o??$user)->state ?? ''"/>
</div>
<div class="col-12 col-md-4">
<x-leenooks::form.text name="postcode" label="Post Code" :value="($o??$user)->postcode ?? ''"/>
</div>
</div>
<div class="row">
<div class="col-12 col-md-6">
<x-leenooks::form.select id="country" name="country_id" icon="fa-globe" label="Country" :value="($o??$user)->country_id ?? ''" :options="Country::select(['id','name'])->active()->get()->map(function($item) { $item->value = $item->name; return $item; })->toArray()"/>
</div>
</div>
</div>
</div>
<div class="row pt-3">
<div class="col">
<button type="reset" name="cancel" class="btn btn-danger">Cancel</button>
<button type="submit" name="submit" class="btn btn-success float-right">Save</button>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
@endsection
@section('page-scripts')
<!-- Passkeys -->
<script type='text/javascript' src='{{ asset('/passkey/passkey.js') }}'></script>
<script type="text/javascript">
$(document).ready(function() {
$('#passkey').on('click',function(item) {
return passkey_create($(this),'{{ csrf_token() }}','fa-key','{{ ($o??$user)->passkey ? 'btn-success' : 'btn-outline-secondary' }}','btn-success','{{ ($o??$user)->passkey ? 'btn-secondary' : 'btn-outline-secondary' }}');
});
});
</script>
@append

View File

@@ -0,0 +1,161 @@
<!-- Main Header -->
<!-- Navbar -->
<nav class="main-header navbar navbar-expand bg-white navbar-light border-bottom">
<!-- Left navbar links -->
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link" data-widget="pushmenu" href="#"><i class="fas fa-bars"></i></a>
</li>
</ul>
<!-- SEARCH FORM -->
<form class="form-inline ml-3">
<div class="input-group input-group-sm">
<input class="form-control form-control-navbar" name="q" type="search" placeholder="Search" aria-label="Search" autocomplete="off">
<div class="input-group-append">
<span class="input-group-text"><i class="fas fa-search"></i></span>
<span class="p-1 d-none" name="searching"><i class="fas fa-spinner fa-spin" style="margin-top: .33em; width: 1em; height: 1em;"></i></span>
</div>
<div id="search_results"></div>
</div>
</form>
<!-- Right navbar links -->
<ul class="navbar-nav ml-auto">
@include('adminlte::layouts.partials.topmenu')
@if(Auth::check())
<!-- Profile Settings -->
<li class="nav-item dropdown">
<a class="nav-link" data-toggle="dropdown" href="#">
<i class="fas fa-cog"></i>
</a>
<div class="dropdown-menu dropdown-menu-lg dropdown-menu-right">
<span class="dropdown-item dropdown-header @if($user->switched) bg-danger @endif">
@if($user->switched)
SUDO (<small>{{ $user->name ?: 'User Name' }}</small>)
@else
{{ $user->name ?: 'User Name' }}
@endif
</span>
<div class="dropdown-divider"></div>
<a href="{{ url('u/settings') }}" class="dropdown-item">
<i class="fas fa-user mr-2"></i> Settings
</a>
<div class="dropdown-divider"></div>
@if ($user->switched)
<a href="{{ url('/admin/switch/stop') }}" class="dropdown-item">
<i class="fas fa-sign-out-alt mr-2"></i> {{ trans('adminlte_lang::message.switchoff') }}
</a>
@else
<a href="{{ url('logout') }}" class="dropdown-item">
<i class="fas fa-sign-out-alt mr-2"></i> Log Out
</a>
@endif
</div>
</li>
@else
<a href="{{ url()->current().'?login=1' }}" class="text-muted pr-2"><i class="fas fa-lock"></i></a>
@endif
<!-- Control Side Bar -->
@isset($controlsidebar)
<li class="nav-item">
<a class="nav-link" data-widget="control-sidebar" data-slide="true" href="#">
<i class="fas fa-th"></i>
</a>
</li>
@endisset
</ul>
</nav>
@section('page-scripts')
<style>
/* Solid border */
div.typeahead.dropdown-menu > .dropdown-header {
color: #000000;
text-align: left;
}
</style>
<script type="text/javascript">
$(document).ready(function() {
$('input[name=q]').typeahead({
autoSelect: false,
scrollHeight: 10,
theme: 'bootstrap4',
delay: 500,
minLength: 2,
items: {{ isset($search_limit) ? $search_limit : 100 }},
fitToElement: false,
selectOnBlur: false,
appendTo: "#search_results",
source: function (query,process) {
search('{{ url("search",['date'=>isset($ido) ? $ido->id : NULL]) }}',query,process);
},
matcher: function () { return true; },
// Disable sorting and just return the items (items should by the ajax method)
sorter: function(items) {
return items;
},
updater: function (item) {
window.parent.location.href = item.value;
},
})
.on('keyup keypress', function(event) {
var key = event.keyCode || event.which;
if (key === 13) {
event.preventDefault();
return false;
}
});
});
var c=0;
var search = _.debounce(function(url,query,process,icon){
$.ajax({
url : url,
type : 'GET',
data : 'term=' + query,
dataType : 'JSON',
async : true,
cache : false,
beforeSend : function() {
if (c++ == 0) {
if (icon)
$('i[name='+icon+']').addClass("fa-spin");
else {
$('span[name=searching]').removeClass("d-none");
}
}
},
success : function(data) {
// if json is null, means no match, won't do again.
if(data==null || (data.length===0)) return;
process(data);
},
complete : function() {
if (--c == 0) {
if (icon)
$('i[name='+icon+']').removeClass("fa-spin");
else {
$('span[name=searching]').addClass("d-none");
}
}
},
statusCode: {
401: function() {
window.parent.location.href = '{{ route('login') }}';
}
}
})
}, 500);
</script>
@append