Foundation for Check Password and password functions - only Clear is currently implemented
This commit is contained in:
parent
30f964b849
commit
08e838d40a
@ -11,10 +11,11 @@ use App\Classes\LDAP\Schema\AttributeType;
|
|||||||
/**
|
/**
|
||||||
* Represents an attribute of an LDAP Object
|
* Represents an attribute of an LDAP Object
|
||||||
*/
|
*/
|
||||||
class Attribute implements \Countable, \ArrayAccess
|
class Attribute implements \Countable, \ArrayAccess, \Iterator
|
||||||
{
|
{
|
||||||
// Attribute Name
|
// Attribute Name
|
||||||
protected string $name;
|
protected string $name;
|
||||||
|
private int $counter = 0;
|
||||||
|
|
||||||
protected ?AttributeType $schema = NULL;
|
protected ?AttributeType $schema = NULL;
|
||||||
|
|
||||||
@ -174,6 +175,31 @@ class Attribute implements \Countable, \ArrayAccess
|
|||||||
$this->values->push($value);
|
$this->values->push($value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function current(): mixed
|
||||||
|
{
|
||||||
|
return $this->values->get($this->counter);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function next(): void
|
||||||
|
{
|
||||||
|
$this->counter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function key(): mixed
|
||||||
|
{
|
||||||
|
return $this->counter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function valid(): bool
|
||||||
|
{
|
||||||
|
return $this->values->has($this->counter);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function rewind(): void
|
||||||
|
{
|
||||||
|
$this->counter = 0;
|
||||||
|
}
|
||||||
|
|
||||||
public function count(): int
|
public function count(): int
|
||||||
{
|
{
|
||||||
return $this->values->count();
|
return $this->values->count();
|
||||||
@ -181,7 +207,7 @@ class Attribute implements \Countable, \ArrayAccess
|
|||||||
|
|
||||||
public function offsetExists(mixed $offset): bool
|
public function offsetExists(mixed $offset): bool
|
||||||
{
|
{
|
||||||
return ! is_null($this->values->get($offset));
|
return ! is_null($this->values->has($offset));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function offsetGet(mixed $offset): mixed
|
public function offsetGet(mixed $offset): mixed
|
||||||
|
@ -4,7 +4,9 @@ namespace App\Classes\LDAP\Attribute;
|
|||||||
|
|
||||||
use Illuminate\Contracts\View\View;
|
use Illuminate\Contracts\View\View;
|
||||||
use Illuminate\Support\Arr;
|
use Illuminate\Support\Arr;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
|
use App\Classes\LDAP\Attribute\Password\Base;
|
||||||
use App\Classes\LDAP\Attribute;
|
use App\Classes\LDAP\Attribute;
|
||||||
use App\Traits\MD5Updates;
|
use App\Traits\MD5Updates;
|
||||||
|
|
||||||
@ -14,6 +16,52 @@ use App\Traits\MD5Updates;
|
|||||||
final class Password extends Attribute
|
final class Password extends Attribute
|
||||||
{
|
{
|
||||||
use MD5Updates;
|
use MD5Updates;
|
||||||
|
private const password_helpers = 'Classes/LDAP/Attribute/Password';
|
||||||
|
public const commands = 'App\\Classes\\LDAP\\Attribute\\Password\\';
|
||||||
|
|
||||||
|
private static function helpers(): Collection
|
||||||
|
{
|
||||||
|
$helpers = collect();
|
||||||
|
|
||||||
|
foreach (preg_grep('/^([^.])/',scandir(app_path(self::password_helpers))) as $file) {
|
||||||
|
if (($file === 'Base.php') || (! str_ends_with(strtolower($file),'.php')))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
$class = self::commands.preg_replace('/\.php$/','',$file);
|
||||||
|
if ($helpers->count())
|
||||||
|
$helpers->push('');
|
||||||
|
|
||||||
|
$helpers = $helpers
|
||||||
|
->merge([$class::id()=>$class]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $helpers;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the object that will process a password
|
||||||
|
*
|
||||||
|
* @param string $id
|
||||||
|
* @return Base|null
|
||||||
|
*/
|
||||||
|
public static function hash(string $id): ?Attribute\Password\Base
|
||||||
|
{
|
||||||
|
return ($helpers=static::helpers())->has($id) ? new ($helpers->get($id)) : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given an LDAP password syntax {xxx}yyyyyy, this function will return xxx
|
||||||
|
*
|
||||||
|
* @param string $password
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function hash_id(string $password): string
|
||||||
|
{
|
||||||
|
$m = [];
|
||||||
|
preg_match('/^{([A-Z]+)}(.*)$/',$password,$m);
|
||||||
|
|
||||||
|
return Arr::get($m,1,'Clear');
|
||||||
|
}
|
||||||
|
|
||||||
public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE): View
|
public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE): View
|
||||||
{
|
{
|
||||||
@ -21,7 +69,8 @@ final class Password extends Attribute
|
|||||||
->with('o',$this)
|
->with('o',$this)
|
||||||
->with('edit',$edit)
|
->with('edit',$edit)
|
||||||
->with('old',$old)
|
->with('old',$old)
|
||||||
->with('new',$new);
|
->with('new',$new)
|
||||||
|
->with('helpers',static::helpers()->map(fn($item,$key)=>['id'=>$key,'value'=>$key]));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function render_item_old(int $key): ?string
|
public function render_item_old(int $key): ?string
|
||||||
|
14
app/Classes/LDAP/Attribute/Password/Base.php
Normal file
14
app/Classes/LDAP/Attribute/Password/Base.php
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Classes\LDAP\Attribute\Password;
|
||||||
|
|
||||||
|
abstract class Base
|
||||||
|
{
|
||||||
|
abstract public function compare(string $source,string $compare): bool;
|
||||||
|
abstract public function encode(string $password): string;
|
||||||
|
|
||||||
|
public static function id(): string
|
||||||
|
{
|
||||||
|
return static::key;
|
||||||
|
}
|
||||||
|
}
|
18
app/Classes/LDAP/Attribute/Password/Clear.php
Normal file
18
app/Classes/LDAP/Attribute/Password/Clear.php
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Classes\LDAP\Attribute\Password;
|
||||||
|
|
||||||
|
final class Clear extends Base
|
||||||
|
{
|
||||||
|
public const key = 'Clear';
|
||||||
|
|
||||||
|
public function compare(string $source,string $compare): bool
|
||||||
|
{
|
||||||
|
return $source === $compare;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function encode(string $password): string
|
||||||
|
{
|
||||||
|
return $password;
|
||||||
|
}
|
||||||
|
}
|
@ -90,6 +90,25 @@ class HomeController extends Controller
|
|||||||
return $x->render();
|
return $x->render();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function entry_password_check(Request $request)
|
||||||
|
{
|
||||||
|
$dn = Crypt::decryptString($request->dn);
|
||||||
|
$o = config('server')->fetch($dn);
|
||||||
|
|
||||||
|
$password = $o->getObject('userpassword');
|
||||||
|
|
||||||
|
$result = collect();
|
||||||
|
foreach ($password as $key => $value) {
|
||||||
|
$type = $password->hash_id($value);
|
||||||
|
$compare = Arr::get($request->password,$key);
|
||||||
|
//Log::debug(sprintf('comparing [%s] with [%s] type [%s]',$value,$compare,$type));
|
||||||
|
|
||||||
|
$result->push((($compare !== NULL) && Attribute\Password::hash($type)->compare($value,$compare)) ? 'OK' :'FAIL');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show a confirmation to update a DN
|
* Show a confirmation to update a DN
|
||||||
*
|
*
|
||||||
@ -103,9 +122,19 @@ class HomeController extends Controller
|
|||||||
|
|
||||||
$o = config('server')->fetch($dn);
|
$o = config('server')->fetch($dn);
|
||||||
|
|
||||||
foreach ($request->except(['_token','dn']) as $key => $value)
|
foreach ($request->except(['_token','dn','userpassword_hash','userpassword']) as $key => $value)
|
||||||
$o->{$key} = array_filter($value);
|
$o->{$key} = array_filter($value);
|
||||||
|
|
||||||
|
// We need to process and encrypt the password
|
||||||
|
$passwords = [];
|
||||||
|
foreach ($request->userpassword as $key => $value) {
|
||||||
|
if ($value) {
|
||||||
|
$type = Arr::get($request->userpassword_hash,$key);
|
||||||
|
array_push($passwords,Attribute\Password::hash($type)->encode($value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$o->userpassword = $passwords;
|
||||||
|
|
||||||
if (! $o->getDirty())
|
if (! $o->getDirty())
|
||||||
return back()
|
return back()
|
||||||
->withInput()
|
->withInput()
|
||||||
|
@ -52,11 +52,17 @@ class Entry extends Model
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine if the new and old values for a given key are equivalent.
|
* Determine if the new and old values for a given key are equivalent.
|
||||||
|
*
|
||||||
|
* @todo This function barfs on language tags, eg: key = givenname;lang-ja
|
||||||
*/
|
*/
|
||||||
protected function originalIsEquivalent(string $key): bool
|
protected function originalIsEquivalent(string $key): bool
|
||||||
{
|
{
|
||||||
$key = $this->normalizeAttributeKey($key);
|
$key = $this->normalizeAttributeKey($key);
|
||||||
|
|
||||||
|
// @todo Silently ignore keys of language tags - we should work with them
|
||||||
|
if (str_contains($key,';'))
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
return ((! array_key_exists($key,$this->original)) && (! $this->objects->has($key)))
|
return ((! array_key_exists($key,$this->original)) && (! $this->objects->has($key)))
|
||||||
|| (! $this->getObject($key)->isDirty());
|
|| (! $this->getObject($key)->isDirty());
|
||||||
}
|
}
|
||||||
|
@ -153,13 +153,25 @@ return [
|
|||||||
'mail' => [
|
'mail' => [
|
||||||
'mail'=>[
|
'mail'=>[
|
||||||
'sometimes',
|
'sometimes',
|
||||||
'array','min:1'
|
'array',
|
||||||
|
'min:1'
|
||||||
],
|
],
|
||||||
'mail.*' => [
|
'mail.*' => [
|
||||||
'nullable',
|
'nullable',
|
||||||
'email'
|
'email'
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
|
'userpassword' => [
|
||||||
|
'userpassword' => [
|
||||||
|
'sometimes',
|
||||||
|
'array',
|
||||||
|
'min:1'
|
||||||
|
],
|
||||||
|
'userpassword.*' => [
|
||||||
|
'nullable',
|
||||||
|
'min:8'
|
||||||
|
]
|
||||||
|
],
|
||||||
'uidnumber' => [
|
'uidnumber' => [
|
||||||
'uidnumber' => [
|
'uidnumber' => [
|
||||||
'sometimes',
|
'sometimes',
|
||||||
|
10
public/css/custom.css
vendored
10
public/css/custom.css
vendored
@ -3,3 +3,13 @@ img.jpegphoto {
|
|||||||
max-width:100px;
|
max-width:100px;
|
||||||
height:100px;
|
height:100px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** ensure our userpassword has select is next to the password input */
|
||||||
|
div#userpassword .select2-container--bootstrap-5 .select2-selection {
|
||||||
|
font-size: inherit;
|
||||||
|
border-bottom-right-radius: unset;
|
||||||
|
border-top-right-radius: unset;
|
||||||
|
width: 7em;
|
||||||
|
border: #444054 1px solid;
|
||||||
|
background-color: #f0f0f0;
|
||||||
|
}
|
@ -5,6 +5,6 @@
|
|||||||
{{ $slot }}
|
{{ $slot }}
|
||||||
</div>
|
</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>
|
||||||
</div>
|
</div>
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
{{ $value }}
|
{{ $value }}
|
||||||
@if ($o->isStructural($value))
|
@if ($o->isStructural($value))
|
||||||
<input type="hidden" name="{{ $o->name_lc }}[]" value="{{ $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
|
@endif
|
||||||
<br>
|
<br>
|
||||||
@endif
|
@endif
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
<!-- @todo We are not handling redirect backs with updated values -->
|
|
||||||
<!-- $o=Password::class -->
|
<!-- $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)
|
@foreach($o->values as $value)
|
||||||
@if($edit)
|
@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)>
|
<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">
|
<div class="invalid-feedback pb-2">
|
||||||
@ -13,13 +13,17 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@else
|
@else
|
||||||
{{ str_repeat('x',8) }}
|
{{ (($x=$o->hash_id($value)) && ($x !== 'Clear')) ? sprintf('{%s}',$x) : '' }}{{ str_repeat('x',8) }}
|
||||||
@endif
|
@endif
|
||||||
@endforeach
|
@endforeach
|
||||||
|
</x-attribute.layout>
|
||||||
|
|
||||||
@if($edit)
|
@if($edit)
|
||||||
|
<div class="row">
|
||||||
|
<div class="offset-1 col-4 p-2">
|
||||||
<span class="p-0 m-0">
|
<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>
|
<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>
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@endif
|
@endif
|
||||||
</x-attribute.layout>
|
|
@ -3,23 +3,11 @@
|
|||||||
@elseif($edit && $o->can_addvalues)
|
@elseif($edit && $o->can_addvalues)
|
||||||
<span class="p-0 m-0">
|
<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>
|
<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>
|
</span>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
@section('page-scripts')
|
@section('page-scripts')
|
||||||
@if(($edit && $o->can_addvalues))
|
@if($edit && $o->can_addvalues)
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
// Create a new entry when Add Value clicked
|
// Create a new entry when Add Value clicked
|
||||||
|
@ -52,7 +52,7 @@
|
|||||||
theme: 'bootstrap-5',
|
theme: 'bootstrap-5',
|
||||||
dropdownAutoWidth: true,
|
dropdownAutoWidth: true,
|
||||||
width: 'style',
|
width: 'style',
|
||||||
allowClear: true,
|
allowClear: {{ $allowclear ?? 'true' }},
|
||||||
placeholder: '{{ $placeholder ?? '' }}',
|
placeholder: '{{ $placeholder ?? '' }}',
|
||||||
@isset($addvalues)
|
@isset($addvalues)
|
||||||
tags: true,
|
tags: true,
|
||||||
|
@ -112,7 +112,7 @@
|
|||||||
@endsection
|
@endsection
|
||||||
|
|
||||||
@section('page-modals')
|
@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 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-dialog modal-lg modal-fullscreen-xl-down">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
@ -127,11 +127,47 @@
|
|||||||
|
|
||||||
<div class="modal-footer">
|
<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-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>
|
||||||
</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
|
@endsection
|
||||||
|
|
||||||
@section('page-scripts')
|
@section('page-scripts')
|
||||||
@ -156,6 +192,11 @@
|
|||||||
$(this).attr('readonly',false);
|
$(this).attr('readonly',false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Our password type
|
||||||
|
$('div#userpassword .form-select').each(function() {
|
||||||
|
$(this).prop('disabled',false);
|
||||||
|
})
|
||||||
|
|
||||||
$('.row.d-none').removeClass('d-none');
|
$('.row.d-none').removeClass('d-none');
|
||||||
$('.addable.d-none').removeClass('d-none');
|
$('.addable.d-none').removeClass('d-none');
|
||||||
$('.deletable.d-none').removeClass('d-none');
|
$('.deletable.d-none').removeClass('d-none');
|
||||||
@ -208,7 +249,6 @@
|
|||||||
$('#entry-export-modal').on('shown.bs.modal',function() {
|
$('#entry-export-modal').on('shown.bs.modal',function() {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: 'GET',
|
type: 'GET',
|
||||||
beforeSend: function() {},
|
|
||||||
success: function(data) {
|
success: function(data) {
|
||||||
$('#entry-export').empty().append(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())
|
@if(old())
|
||||||
editmode();
|
editmode();
|
||||||
@endif
|
@endif
|
||||||
|
@ -42,5 +42,6 @@ Route::post('entry/update/commit',[HomeController::class,'entry_update']);
|
|||||||
Route::post('entry/update/pending',[HomeController::class,'entry_pending_update']);
|
Route::post('entry/update/pending',[HomeController::class,'entry_pending_update']);
|
||||||
Route::get('entry/newattr/{id}',[HomeController::class,'entry_newattr']);
|
Route::get('entry/newattr/{id}',[HomeController::class,'entry_newattr']);
|
||||||
Route::get('entry/export/{id}',[HomeController::class,'entry_export']);
|
Route::get('entry/export/{id}',[HomeController::class,'entry_export']);
|
||||||
|
Route::post('entry/password/check/',[HomeController::class,'entry_password_check']);
|
||||||
|
|
||||||
Route::post('import/process/{type}',[HomeController::class,'import']);
|
Route::post('import/process/{type}',[HomeController::class,'import']);
|
Loading…
x
Reference in New Issue
Block a user