Start of work to enable creation of new entries
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 1m33s
Create Docker Image / Build Docker Image (arm64) (push) Successful in 4m36s
Create Docker Image / Final Docker Image Manifest (push) Successful in 10s

This commit is contained in:
Deon George 2025-02-23 18:14:41 +11:00
parent 176be19043
commit 1e19213566
11 changed files with 225 additions and 47 deletions

View File

@ -22,15 +22,15 @@ class APIController extends Controller
{
$base = Server::baseDNs() ?: collect();
return $base->transform(function($item) {
return [
'title'=>$item->getRdn(),
'item'=>$item->getDNSecure(),
'lazy'=>TRUE,
'icon'=>'fa-fw fas fa-sitemap',
'tooltip'=>$item->getDn(),
];
});
return $base
->transform(fn($item)=>
[
'title'=>$item->getRdn(),
'item'=>$item->getDNSecure(),
'lazy'=>TRUE,
'icon'=>'fa-fw fas fa-sitemap',
'tooltip'=>$item->getDn(),
]);
}
/**
@ -45,15 +45,22 @@ class APIController extends Controller
return (config('server'))
->children($dn)
->transform(function($item) {
return [
->transform(fn($item)=>
[
'title'=>$item->getRdn(),
'item'=>$item->getDNSecure(),
'icon'=>$item->icon(),
'lazy'=>Arr::get($item->getAttribute('hassubordinates'),0) == 'TRUE',
'tooltip'=>$item->getDn(),
];
});
])
->prepend(
[
'title'=>sprintf('[%s]',__('Create Entry')),
'item'=>Crypt::encryptString(sprintf('*%s|%s','create_new',$dn)),
'lazy'=>FALSE,
'icon'=>'fas fa-fw fa-square-plus text-warning',
'tooltip'=>__('Create new LDAP item here'),
]);
}
public function schema_view(Request $request)

View File

@ -2,6 +2,9 @@
namespace App\Http\Controllers;
use Illuminate\Contracts\View\Factory;
use Illuminate\Contracts\View\View;
use Illuminate\Foundation\Application;
use Illuminate\Http\Request;
use Illuminate\Support\Arr;
use Illuminate\Support\Collection;
@ -12,16 +15,16 @@ use Illuminate\Support\Facades\Redirect;
use LdapRecord\Exceptions\InsufficientAccessException;
use LdapRecord\LdapRecordException;
use LdapRecord\Query\ObjectNotFoundException;
use Nette\NotImplementedException;
use App\Classes\LDAP\{Attribute,Server};
use App\Classes\LDAP\Import\LDIF as LDIFImport;
use App\Classes\LDAP\Export\LDIF as LDIFExport;
use App\Exceptions\Import\{GeneralException,VersionException};
use App\Exceptions\InvalidUsage;
use App\Http\Requests\{EntryRequest,ImportRequest};
use App\Http\Requests\{EntryAdd,EntryRequest,ImportRequest};
use App\Ldap\Entry;
use App\View\Components\AttributeType;
use Nette\NotImplementedException;
class HomeController extends Controller
{
@ -59,13 +62,50 @@ class HomeController extends Controller
public function dn_frame(Request $request)
{
$dn = Crypt::decryptString($request->post('key'));
$cmd = '';
$page_actions = collect(['edit'=>TRUE,'copy'=>TRUE]);
if (str_contains($dn,'|')) {
$m = [];
return view('frames.dn')
->with('o',config('server')->fetch($dn))
->with('dn',$dn)
->with('page_actions',$page_actions);
if (preg_match('/\*([a-z_]+)\|(.+)$/',$dn,$m)) {
$cmd = $m[1];
$dn = $m[2];
}
}
return match ($cmd) {
'create_new' => view('frames.create')
->with('o',config('server')->fetch($dn))
->with('step',0)
->with('dn',$dn),
default => view('frames.dn')
->with('o',config('server')->fetch($dn))
->with('dn',$dn)
->with('page_actions',collect(['edit'=>TRUE,'copy'=>TRUE])),
};
}
/**
* Create a new object in the LDAP server
*
* @param EntryAdd $request
* @return Factory|View|Application|object
*/
public function entry_add(EntryAdd $request)
{
switch ($request->step) {
case 1:
return view('frame')
->with('subframe',$request->frame)
->with('bases',$this->bases())
->with('o',config('server')->fetch($x=Crypt::decryptString($request->dn)))
->with('step',$request->step)
->with('dn',$x);
default:
dd($request);
}
}
/**
@ -259,26 +299,30 @@ class HomeController extends Controller
}
/**
* Application home page
* This is the main page render function
*
* If a DN is set, when render a DN info/edit frame
* If a frame is set, then we render that (sub)frame
*/
public function home()
{
if (old('dn'))
if (old('frame'))
return view('frame')
->with('subframe',old('frame'))
->with('bases',$this->bases())
->with('o',old('dn') ? config('server')->fetch($dn=Crypt::decryptString(old('dn'))) : NULL)
->with('dn',$dn ?? NULL);
elseif (old('dn'))
return view('frame')
->with('subframe','dn')
->with('bases',$this->bases())
->with('o',config('server')->fetch($dn=Crypt::decryptString(old('dn'))))
->with('dn',$dn);
elseif (old('frame'))
return view('frame')
->with('subframe',old('frame'))
->with('bases',$this->bases());
else
return view('home')
->with('bases',$this->bases())
->with('server',config('ldap.connections.default.name'));
->with('bases',$this->bases());
}
/**

View File

@ -0,0 +1,33 @@
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
use App\Rules\{DNExists,StructuralObjectClass};
class EntryAdd extends FormRequest
{
/**
* Get the validation rules that apply to the request.
*
* @return array<string, mixed>
*/
public function rules(): array
{
return [
'dn' => new DNExists,
'objectclass' => [
'required',
'string',
new StructuralObjectClass,
],
'step' => 'int|min:1|max:2',
'frame' => [
'string',
Rule::in(['create']),
]
];
}
}

View File

@ -6,22 +6,12 @@ use Illuminate\Foundation\Http\FormRequest;
class EntryRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return TRUE;
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, mixed>
*/
public function rules()
public function rules(): array
{
return config('server')
->schema('attributetypes')

View File

@ -6,12 +6,7 @@ use Illuminate\Foundation\Http\FormRequest;
class ImportRequest extends FormRequest
{
public function authorize()
{
return TRUE;
}
public function rules()
public function rules(): array
{
return [
'frame' => 'required|string|in:import',

21
app/Rules/DNExists.php Normal file
View File

@ -0,0 +1,21 @@
<?php
namespace App\Rules;
use Closure;
use Illuminate\Contracts\Validation\ValidationRule;
use Illuminate\Support\Facades\Crypt;
class DNExists implements ValidationRule
{
/**
* Run the validation rule.
*
* @param \Closure(string, ?string=): \Illuminate\Translation\PotentiallyTranslatedString $fail
*/
public function validate(string $attribute,mixed $value,Closure $fail): void
{
if (! config('server')->fetch($x=Crypt::decryptString($value)))
$fail(sprintf('The DN %s doesnt exist.',$x));
}
}

View File

@ -0,0 +1,20 @@
<?php
namespace App\Rules;
use Closure;
use Illuminate\Contracts\Validation\ValidationRule;
class StructuralObjectClass implements ValidationRule
{
/**
* Run the validation rule.
*
* @param \Closure(string, ?string=): \Illuminate\Translation\PotentiallyTranslatedString $fail
*/
public function validate(string $attribute,mixed $value,Closure $fail): void
{
if (! config('server')->schema('objectclasses',$value)->isStructural())
$fail(sprintf('The object class %s is not a StructuralObject class.',$value));
}
}

View File

@ -51,7 +51,6 @@
$('select#newoc').select2({
dropdownParent: $('#new_objectclass-modal'),
theme: 'bootstrap-5',
allowClear: true,
multiple: true,
data: data,
});

View File

@ -54,10 +54,14 @@
width: 'style',
allowClear: {{ $allowclear ?? 'true' }},
placeholder: '{{ $placeholder ?? '' }}',
multiple: {{ $multiple ?? 'false' }},
@isset($addvalues)
tags: true,
@endisset
});
$('#{{ $id ?? $name }}').val(' ');
$('#{{ $id ?? $name }}').trigger('change');
});
</script>
@append

View File

@ -0,0 +1,64 @@
@extends('layouts.dn')
@section('page_title')
@include('fragment.dn.header')
@endsection
@section('main-content')
<div class="row">
<div class="offset-1 col-10">
<div class="main-card mb-3 card">
<form id="import-form" action="{{ url('entry/add') }}" method="POST" enctype="multipart/form-data">
@csrf
<input type="hidden" name="frame" value="create">
<input type="hidden" name="dn" value="{{ Crypt::encryptString($dn) }}">
<input type="hidden" name="step" value="{{ ++$step }}">
<div class="card-header">
@lang('Create New Entry')
</div>
@switch($step)
@case(1)
<div class="card-body">
<div class="row">
<div class="col-12 col-sm-6">
<x-form.select
name="objectclass"
:label="__('Select a Structural Object Class...')"
:options="($oc=config('server')->schema('objectclasses'))
->filter(fn($item)=>$item->isStructural())
->sortBy(fn($item)=>$item->name_lc)
->map(fn($item,$key)=>['id'=>$key,'value'=>$item->name])"
allowclear="false"
multiple="false"
/>
</div>
</div>
</div>
@break
@case(2)
<div class="card-body">
<div class="row">
<div class="col-12 col-sm-6">
<p class="alert alert-danger">
Not ready yet :)
</p>
</div>
</div>
</div>
@break;
@endswitch
<div class="card-footer">
<span class="ms-auto">
<x-form.submit action="Next" form="create-form"/>
</span>
</div>
</form>
</div>
</div>
</div>
@endsection

View File

@ -38,6 +38,7 @@ Route::group(['prefix'=>'user'],function() {
Route::get('image',[HomeController::class,'user_image']);
});
Route::post('entry/add',[HomeController::class,'entry_add']);
Route::get('entry/export/{id}',[HomeController::class,'entry_export']);
Route::post('entry/password/check/',[HomeController::class,'entry_password_check']);
Route::post('entry/attr/add/{id}',[HomeController::class,'entry_attr_add']);