Foundation for Check Password and password functions - only Clear is currently implemented

This commit is contained in:
2025-01-17 17:00:36 +11:00
parent 30f964b849
commit 08e838d40a
15 changed files with 291 additions and 35 deletions

View File

@@ -5,6 +5,6 @@
{{ $slot }}
</div>
<x-attribute.widget.options :o="$o" :edit="$edit" :new="$new"></x-attribute.widget.options>
<x-attribute.widget.options :o="$o" :edit="$edit" :new="$new"/>
</div>
</div>

View File

@@ -14,7 +14,7 @@
{{ $value }}
@if ($o->isStructural($value))
<input type="hidden" name="{{ $o->name_lc }}[]" value="{{ $value }}">
<span class="float-end mb-2">@lang('structural')</span>
<span class="float-end">@lang('structural')</span>
@endif
<br>
@endif

View File

@@ -1,9 +1,9 @@
<!-- @todo We are not handling redirect backs with updated values -->
<!-- $o=Password::class -->
<x-attribute.layout :edit="$edit" :new="$new" :o="$o">
<x-attribute.layout :edit="$edit ?? FALSE" :new="$new ?? FALSE" :o="$o">
@foreach($o->values as $value)
@if($edit)
<div class="input-group has-validation">
<div class="input-group has-validation mb-3">
<x-form.select class="password" id="userpassword_hash_{{$loop->index}}" name="userpassword_hash[]" :value="$o->hash_id($value)" :options="$helpers" allowclear="false" disabled="true"/>
<input type="password" @class(['form-control','is-invalid'=>($e=$errors->get($o->name_lc.'.'.$loop->index)),'mb-1','border-focus'=>$o->values->contains($value)]) name="{{ $o->name_lc }}[]" value="{{ md5($value) }}" @readonly(true)>
<div class="invalid-feedback pb-2">
@@ -13,13 +13,17 @@
</div>
</div>
@else
{{ str_repeat('x',8) }}
{{ (($x=$o->hash_id($value)) && ($x !== 'Clear')) ? sprintf('{%s}',$x) : '' }}{{ str_repeat('x',8) }}
@endif
@endforeach
</x-attribute.layout>
@if($edit)
<span class="p-0 m-0">
<span class="btn btn-sm btn-outline-dark mt-3"><i class="fas fa-user-check"></i> @lang('Check Password')</span>
</span>
@endif
</x-attribute.layout>
@if($edit)
<div class="row">
<div class="offset-1 col-4 p-2">
<span class="p-0 m-0">
<button type="button" class="btn btn-transition btn-sm btn-outline-dark mt-3" data-bs-toggle="modal" data-bs-target="#userpassword-check-modal"><i class="fas fa-user-check"></i> @lang('Check Password')</button>
</span>
</div>
</div>
@endif

View File

@@ -3,23 +3,11 @@
@elseif($edit && $o->can_addvalues)
<span class="p-0 m-0">
<span @class(['btn','btn-sm','btn-outline-primary','mt-3','addable','d-none'=>(! $new)]) id="{{ $o->name_lc }}"><i class="fas fa-fw fa-plus"></i> @lang('Add Value')</span>
@if($new)
<script type="text/javascript">
$(document).ready(function() {
// Create a new entry when Add Value clicked
$('#{{ $o->name_lc }}.addable').click(function (item) {
var cln = $(this).parent().parent().find('input:last').clone();
cln.val('').attr('placeholder', '[@lang('NEW')]');
cln.appendTo('#' + item.currentTarget.id)
});
});
</script>
@endif
</span>
@endif
@section('page-scripts')
@if(($edit && $o->can_addvalues))
@if($edit && $o->can_addvalues)
<script type="text/javascript">
$(document).ready(function() {
// Create a new entry when Add Value clicked

View File

@@ -52,7 +52,7 @@
theme: 'bootstrap-5',
dropdownAutoWidth: true,
width: 'style',
allowClear: true,
allowClear: {{ $allowclear ?? 'true' }},
placeholder: '{{ $placeholder ?? '' }}',
@isset($addvalues)
tags: true,

View File

@@ -112,7 +112,7 @@
@endsection
@section('page-modals')
<!-- Modal -->
<!-- EXPORT -->
<div class="modal fade" id="entry-export-modal" tabindex="-1" aria-labelledby="entry-export-label" aria-hidden="true">
<div class="modal-dialog modal-lg modal-fullscreen-xl-down">
<div class="modal-content">
@@ -127,11 +127,47 @@
<div class="modal-footer">
<button type="button" class="btn btn-secondary btn-sm" data-bs-dismiss="modal">Close</button>
<button id="entry-export-download" type="button" class="btn btn-primary btn-sm">Download</button>
<button type="button" class="btn btn-primary btn-sm" id="entry-export-download">Download</button>
</div>
</div>
</div>
</div>
@if($up=$o->getObject('userpassword'))
<!-- CHECK USERPASSWORD -->
<div class="modal fade" id="userpassword-check-modal" tabindex="-1" aria-labelledby="userpassword-check-label" aria-hidden="true">
<div class="modal-dialog modal-md modal-fullscreen-md-down">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="userpassword-check-label">Check Passwords for {{ $dn }}</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<table class="table table-bordered p-1">
@foreach($up->values as $key => $value)
<tr>
<th>Check</th>
<td>{{ (($xx=$up->hash_id($value)) && ($xx !== 'Clear')) ? sprintf('{%s}',$xx) : '' }}{{ str_repeat('x',8) }}</td>
<td>
<input type="password" style="width: 90%" name="password[{{$key}}]"> <i class="fas fa-fw fa-lock"></i>
<div class="invalid-feedback pb-2">
Invalid Password
</div>
</td>
</tr>
@endforeach
</table>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary btn-sm" data-bs-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary btn-sm" id="userpassword_check_submit"><i class="fas fa-fw fa-spinner fa-spin d-none"></i> Check</button>
</div>
</div>
</div>
</div>
@endif
@endsection
@section('page-scripts')
@@ -156,6 +192,11 @@
$(this).attr('readonly',false);
});
// Our password type
$('div#userpassword .form-select').each(function() {
$(this).prop('disabled',false);
})
$('.row.d-none').removeClass('d-none');
$('.addable.d-none').removeClass('d-none');
$('.deletable.d-none').removeClass('d-none');
@@ -205,10 +246,9 @@
download('ldap-export.ldif',ldif.html());
});
$('#entry-export-modal').on('shown.bs.modal', function () {
$('#entry-export-modal').on('shown.bs.modal',function() {
$.ajax({
type: 'GET',
beforeSend: function() {},
success: function(data) {
$('#entry-export').empty().append(data);
},
@@ -221,6 +261,65 @@
})
})
@if($up)
$('button[id=userpassword_check_submit]').on('click',function(item) {
var that = $(this);
var passwords = $('#userpassword-check-modal')
.find('input[name^="password["')
.map((key,item)=>item.value);
if (passwords.length === 0) return false;
$.ajax({
type: 'POST',
beforeSend: function() {
// Disable submit, add spinning icon
that.prop('disabled',true);
that.find('i').removeClass('d-none');
},
complete: function() {
that.prop('disabled',false);
that.find('i').addClass('d-none');
},
success: function(data) {
data.forEach(function(item,key) {
var i = $('#userpassword-check-modal')
.find('input[name="password['+key+']')
.siblings('i');
var feedback = $('#userpassword-check-modal')
.find('input[name="password['+key+']')
.siblings('div.invalid-feedback');
console.log(feedback.attr('display'));
if (item === 'OK') {
i.removeClass('text-danger').addClass('text-success').removeClass('fa-lock').addClass('fa-lock-open');
if (feedback.is(':visible'))
feedback.hide();
} else {
i.removeClass('text-success').addClass('text-danger').removeClass('fa-lock-open').addClass('fa-lock');
if (! feedback.is(':visible'))
feedback.show();
}
})
},
error: function(e) {
if (e.status != 412)
alert('That didnt work? Please try again....');
},
url: '{{ url('entry/password/check') }}',
data: {
dn: '{{ $o->getDNSecure() }}',
password: Array.from(passwords),
},
dataType: 'json',
cache: false
})
});
@endif
@if(old())
editmode();
@endif