Enable creation of new entries via templates

This commit is contained in:
2025-06-11 19:28:38 +09:30
parent 820f398c2c
commit 9f0290bd40
7 changed files with 100 additions and 22 deletions

View File

@@ -30,15 +30,20 @@ class Template
public function __get(string $key): mixed
{
return match ($key) {
'attributes' => array_map('strtolower',array_keys(Arr::get($this->template,$key))),
'objectclasses' => array_map('strtolower',Arr::get($this->template,$key)),
'enabled' => Arr::get($this->template,$key,FALSE),
'icon','regexp' => Arr::get($this->template,$key),
'attributes' => collect(array_map('strtolower',array_keys(Arr::get($this->template,$key)))),
'objectclasses' => collect(array_map('strtolower',Arr::get($this->template,$key))),
'enabled' => Arr::get($this->template,$key,FALSE) && (! $this->invalid),
'icon','regexp','title' => Arr::get($this->template,$key),
default => throw new \Exception('Unknown key: '.$key),
};
}
public function __isset(string $key): bool
{
return array_key_exists($key,$this->template);
}
public function __toString(): string
{
return $this->invalid ? '' : Arr::get($this->template,'title','No Template Name');

View File

@@ -55,16 +55,24 @@ class HomeController extends Controller
$key = $this->request_key($request,collect(old()));
$template = NULL;
$o = new Entry;
$o->setRDNBase($key['dn']);
if (count($x=array_filter(old('objectclass',$request->objectclass)))) {
$o->objectclass = $x;
if (count($x=collect(old('objectclass',$request->validated('objectclass')))->dot()->filter())) {
$o->objectclass = Arr::undot($x);
// Also add in our required attributes
foreach($o->getAvailableAttributes()->filter(fn($item)=>$item->required) as $ao)
$o->{$ao->name} = [Entry::TAG_NOTAG=>''];
$o->setRDNBase($key['dn']);
} elseif ($request->validated('template')) {
$template = $o->template($request->validated('template'));
$o->objectclass = [Entry::TAG_NOTAG=>$template->objectclasses->toArray()];
// @todo We need to add aliases
foreach($o->getAvailableAttributes()->filter(fn($item)=>$template->attributes->contains($item)) as $ao)
$o->{$ao->name} = [Entry::TAG_NOTAG=>''];
}
$step = $request->step ? $request->step+1 : old('step');
@@ -74,6 +82,7 @@ class HomeController extends Controller
->with('bases',$this->bases())
->with('o',$o)
->with('step',$step)
->with('template',$template)
->with('container',old('container',$key['dn']));
}
@@ -383,7 +392,12 @@ class HomeController extends Controller
->with('bases',$this->bases());
// If we are rendering a DN, rebuild our object
if ($key['dn']) {
if ($key['cmd'] === 'create') {
$o = new Entry;
$o->setRDNBase($key['dn']);
} elseif ($key['dn']) {
// @todo Need to handle if DN is null, for example if the user's session expired and the ACLs dont let them retrieve $key['dn']
$o = config('server')->fetch($key['dn']);
foreach (collect(old())->except(['key','dn','step','_token','userpassword_hash','rdn','rdn_value']) as $attr => $value)
@@ -393,6 +407,8 @@ class HomeController extends Controller
return match ($key['cmd']) {
'create' => $view
->with('container',old('container',$key['dn']))
->with('o',$o)
->with('template',NULL)
->with('step',1),
'dn' => $view

View File

@@ -66,12 +66,43 @@ class EntryAddRequest extends FormRequest
'min:1',
'max:1',
],
'objectclass._null_'=>[
'required',
'objectclass._null_' => [
function (string $attribute,mixed $value,\Closure $fail) {
$oc = collect($value)->dot()->filter();
// If this is step 1 and there is no objectclass, and no template, then fail
if ((! $oc->count())
&& (request()->post('step') == 1)
&& (! request()->post('template')))
{
$fail(__('Select an objectclass or a template'));
}
// Cant have both an objectclass and a template
if (request()->post('template') && $oc->count())
$fail(__('You cannot select a template and an objectclass'));
},
'array',
'min:1',
new HasStructuralObjectClass,
]
],
'template' => [
function (string $attribute,mixed $value,\Closure $fail) {
$oc = collect(request()->post('objectclass'))->dot()->filter();
// If this is step 1 and there is no objectclass, and no template, then fail
if ((! collect($value)->filter()->count())
&& (request()->post('step') == 1)
&& (! $oc->count()))
{
$fail(__('Select an objectclass or a template'));
}
// Cant have both an objectclass and a template
if ($oc->count() && strlen($value))
$fail(__('You cannot select a template and an objectclass'));
},
],
])
->toArray();
}

View File

@@ -147,7 +147,7 @@ class Entry extends Model
// Filter out our templates specific for this entry
if ($this->dn && (! in_array(strtolower($this->dn),['cn=subschema']))) {
$this->templates = $this->templates
->filter(fn($item)=>! count(array_diff($item->objectclasses,array_map('strtolower',Arr::get($this->attributes,'objectclass')))));
->filter(fn($item)=>! count($item->objectclasses->diff(array_map('strtolower',Arr::get($this->attributes,'objectclass')))));
}
return $this;

View File

@@ -24,6 +24,7 @@ class HasStructuralObjectClass implements ValidationRule
if ($item && config('server')->schema('objectclasses',$item)->isStructural())
return;
$fail('There isnt a Structural Objectclass.');
if (collect($value)->dot()->filter()->count())
$fail(__('There isnt a Structural Objectclass.'));
}
}