Compare commits

...

2 Commits

Author SHA1 Message Date
2b365ef258 Implement DN Entry rename
All checks were successful
Create Docker Image / Test Application (x86_64) (push) Successful in 28s
Create Docker Image / Build Docker Image (x86_64) (push) Successful in 2m11s
Create Docker Image / Build Docker Image (arm64) (push) Successful in 3m15s
Create Docker Image / Final Docker Image Manifest (push) Successful in 10s
2025-07-03 00:21:16 +08:00
719fd67bff Make the ajax calls POST methods, and make the 'Create Entry' in the tree configurable so calls to children() can just return child entries 2025-07-02 23:51:04 +08:00
9 changed files with 107 additions and 15 deletions

View File

@ -48,7 +48,7 @@ Entry Editing:
- [ ] JpegPhoto Create/Delete - [ ] JpegPhoto Create/Delete
- [ ] Binary attribute upload - [ ] Binary attribute upload
- [ ] If removing an objectClass, remove all attributes that only that objectclass provided - [ ] If removing an objectClass, remove all attributes that only that objectclass provided
- [ ] Rename an entry - [ ] Move an entry
- [ ] Group membership selection - [ ] Group membership selection
- [ ] Attribute tag creation - [ ] Attribute tag creation

View File

@ -38,7 +38,7 @@ class AjaxController extends Controller
*/ */
public function children(Request $request): Collection public function children(Request $request): Collection
{ {
$dn = Crypt::decryptString($request->query('_key')); $dn = Crypt::decryptString($request->post('_key'));
// Sometimes our key has a command, so we'll ignore it // Sometimes our key has a command, so we'll ignore it
if (str_starts_with($dn,'*') && ($x=strpos($dn,'|'))) if (str_starts_with($dn,'*') && ($x=strpos($dn,'|')))
@ -57,13 +57,18 @@ class AjaxController extends Controller
'tooltip'=>$item->getDn(), 'tooltip'=>$item->getDn(),
]) ])
->prepend( ->prepend(
[ $request->create
'title'=>sprintf('[%s]',__('Create Entry')), ? [
'item'=>Crypt::encryptString(sprintf('*%s|%s','create',$dn)), 'title'=>sprintf('[%s]',__('Create Entry')),
'lazy'=>FALSE, 'item'=>Crypt::encryptString(sprintf('*%s|%s','create',$dn)),
'icon'=>'fas fa-fw fa-square-plus text-warning', 'lazy'=>FALSE,
'tooltip'=>__('Create new LDAP item here'), 'icon'=>'fas fa-fw fa-square-plus text-warning',
]); 'tooltip'=>__('Create new LDAP item here'),
]
: []
)
->filter()
->values();
} }
public function schema_view(Request $request) public function schema_view(Request $request)

View File

@ -307,6 +307,30 @@ class HomeController extends Controller
->with('o',$o); ->with('o',$o);
} }
public function entry_rename(Request $request): \Illuminate\Http\RedirectResponse|\Illuminate\View\View
{
$from_dn = Crypt::decryptString($request->post('dn'));
Log::info(sprintf('%s:Renaming [%s] to [%s]',self::LOGKEY,$from_dn,$request->post('new_rdn')));
$o = config('server')->fetch($from_dn);
if (! $o)
return back()
->withInput()
->with('note',__('DN doesnt exist'));
try {
$o->rename($request->post('new_rdn'));
} catch (\Exception $e) {
return Redirect::to('/')
->with('failed',$e->getMessage());
}
return Redirect::to('/')
->with('success',[__('Entry renamed')]);
}
/** /**
* Update a DN entry * Update a DN entry
* *

View File

@ -59,7 +59,7 @@ $(document).ready(function() {
if (typeof basedn !== 'undefined') { if (typeof basedn !== 'undefined') {
sources = basedn; sources = basedn;
} else { } else {
sources = { url: '/ajax/bases' }; sources = { method: 'POST', url: '/ajax/bases' };
} }
// Attach the fancytree widget to an existing <div id="tree"> element // Attach the fancytree widget to an existing <div id="tree"> element
@ -95,8 +95,9 @@ $(document).ready(function() {
source: sources, source: sources,
lazyLoad: function(event,data) { lazyLoad: function(event,data) {
data.result = { data.result = {
method: 'POST',
url: '/ajax/children', url: '/ajax/children',
data: {_key: data.node.data.item,depth: 1} data: {_key: data.node.data.item,create: true}
}; };
expandChildren(data.tree.rootNode); expandChildren(data.tree.rootNode);

View File

@ -6,7 +6,7 @@
@php($clone=FALSE) @php($clone=FALSE)
<span class="p-0 m-0"> <span class="p-0 m-0">
@if($o->is_rdn) @if($o->is_rdn)
<button class="btn btn-sm btn-outline-focus mt-3" disabled><i class="fas fa-fw fa-exchange"></i> @lang('Rename')</button> <span id="entry-rename" class="btn btn-sm btn-outline-focus mt-3" data-bs-toggle="modal" data-bs-target="#page-modal"><i class="fas fa-fw fa-exchange"></i> @lang('Rename')</span>
@elseif($edit && $o->can_addvalues) @elseif($edit && $o->can_addvalues)
@switch(get_class($o)) @switch(get_class($o))
@case(Certificate::class) @case(Certificate::class)
@ -26,7 +26,7 @@
@break @break
@case(ObjectClass::class) @case(ObjectClass::class)
<span type="button" @class(['btn','btn-sm','btn-outline-primary','mt-3','addable','d-none'=>(! $new)]) data-bs-toggle="modal" data-bs-target="#new_objectclass-modal"><i class="fas fa-fw fa-plus"></i> @lang('Add Objectclass')</span> <span @class(['btn','btn-sm','btn-outline-primary','mt-3','addable','d-none'=>(! $new)]) data-bs-toggle="modal" data-bs-target="#new_objectclass-modal"><i class="fas fa-fw fa-plus"></i> @lang('Add Objectclass')</span>
<!-- NEW OBJECT CLASS --> <!-- NEW OBJECT CLASS -->
<div class="modal fade" id="new_objectclass-modal" tabindex="-1" aria-labelledby="new_objectclass-label" aria-hidden="true" data-bs-backdrop="static"> <div class="modal fade" id="new_objectclass-modal" tabindex="-1" aria-labelledby="new_objectclass-label" aria-hidden="true" data-bs-backdrop="static">

View File

@ -282,6 +282,25 @@
}) })
break; break;
case 'entry-rename':
$.ajax({
method: 'GET',
url: '{{ url('modal/rename') }}/'+dn,
dataType: 'html',
cache: false,
beforeSend: function() {
that.empty().append('<span class="p-3"><i class="fas fa-3x fa-spinner fa-pulse"></i></span>');
},
success: function(data) {
that.empty().html(data);
},
error: function(e) {
if (e.status !== 412)
alert('That didnt work? Please try again....');
},
});
break;
default: default:
switch ($(item.relatedTarget).attr('name')) { switch ($(item.relatedTarget).attr('name')) {
case 'entry-userpassword-check': case 'entry-userpassword-check':

View File

@ -2,6 +2,7 @@
@section('main-content') @section('main-content')
<x-success/> <x-success/>
<x-failed/>
<div class="card card-solid mb-3"> <div class="card card-solid mb-3">
<div class="card-body"> <div class="card-body">

View File

@ -0,0 +1,40 @@
<div class="modal-header bg-dark text-white">
<h1 class="modal-title fs-5">
<strong>@lang('Rename') <strong>{{ $x=Crypt::decryptString($dn) }}</strong>
</h1>
</div>
<form id="entry-rename-form" method="POST" action="{{ url('entry/rename') }}">
<div class="modal-body">
@csrf
<input type="hidden" name="dn" value="{{ $dn }}">
<div class="row">
<div class="col-12">
<label for="rdn" class="form-label">@lang('New RDN')</label>
<div class="input-group mb-3">
<input type="text" id="rdn" name="new_rdn" class="form-control w-25" placeholder="{{ $rdn=collect(explode(',',$x))->first() }}" value="{{ $rdn }}">
<span class="input-group-text" id="label">{{ collect(explode(',',$x))->skip(1)->join(',') }}</span>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<x-modal.close/>
<button id="entry-rename" type="submit" class="btn btn-sm btn-primary" disabled>@lang('Rename')</button>
</div>
</form>
<script type="text/javascript">
$(document).ready(function() {
var rdn = '{{ $rdn }}';
// Complete the RDN
$('#rdn').on('input',function(item) {
rdn = $(this).val();
$('button[id=entry-rename]').attr('disabled',! rdn.includes('='));
})
});
</script>

View File

@ -49,6 +49,7 @@ Route::controller(HomeController::class)->group(function() {
Route::post('entry/password/check/','entry_password_check'); Route::post('entry/password/check/','entry_password_check');
Route::post('entry/attr/add/{id}','entry_attr_add'); Route::post('entry/attr/add/{id}','entry_attr_add');
Route::post('entry/objectclass/add','entry_objectclass_add'); Route::post('entry/objectclass/add','entry_objectclass_add');
Route::post('entry/rename','entry_rename');
Route::post('entry/update/commit','entry_update'); Route::post('entry/update/commit','entry_update');
Route::post('entry/update/pending','entry_pending_update'); Route::post('entry/update/pending','entry_pending_update');
@ -56,6 +57,7 @@ Route::controller(HomeController::class)->group(function() {
Route::view('modal/delete/{dn}','modals.entry-delete'); Route::view('modal/delete/{dn}','modals.entry-delete');
Route::view('modal/export/{dn}','modals.entry-export'); Route::view('modal/export/{dn}','modals.entry-export');
Route::view('modal/rename/{dn}','modals.entry-rename');
Route::view('modal/userpassword-check/{dn}','modals.entry-userpassword-check'); Route::view('modal/userpassword-check/{dn}','modals.entry-userpassword-check');
}); });
}); });
@ -63,8 +65,8 @@ Route::controller(HomeController::class)->group(function() {
Route::controller(AjaxController::class) Route::controller(AjaxController::class)
->prefix('ajax') ->prefix('ajax')
->group(function() { ->group(function() {
Route::get('bases','bases'); Route::post('bases','bases');
Route::get('children','children'); Route::post('children','children');
Route::post('schema/view','schema_view'); Route::post('schema/view','schema_view');
Route::post('schema/objectclass/attrs/{id}','schema_objectclass_attrs'); Route::post('schema/objectclass/attrs/{id}','schema_objectclass_attrs');
}); });