Pass the template object to the attributes, so we can leverage template rules when rendering attributes

This commit is contained in:
Deon George 2025-06-18 23:32:47 +10:00
parent 5ce3a63878
commit 96afbd8316
20 changed files with 42 additions and 44 deletions

View File

@ -7,6 +7,7 @@ use Illuminate\Support\Arr;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use App\Classes\LDAP\Schema\AttributeType; use App\Classes\LDAP\Schema\AttributeType;
use App\Classes\Template;
use App\Exceptions\InvalidUsage; use App\Exceptions\InvalidUsage;
use App\Ldap\Entry; use App\Ldap\Entry;
@ -326,10 +327,10 @@ class Attribute implements \Countable, \ArrayAccess
* @param bool $old Use old value * @param bool $old Use old value
* @param bool $new Enable adding values * @param bool $new Enable adding values
* @param bool $updated Has the entry been updated (uses rendering highlights)) * @param bool $updated Has the entry been updated (uses rendering highlights))
* @param string|null $template * @param Template|null $template
* @return View * @return View
*/ */
public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,bool $updated=FALSE,?string $template=NULL): View public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,bool $updated=FALSE,?Template $template=NULL): View
{ {
if ($this->is_internal) if ($this->is_internal)
// @note Internal attributes cannot be edited // @note Internal attributes cannot be edited

View File

@ -5,7 +5,7 @@ namespace App\Classes\LDAP\Attribute\Binary;
use Illuminate\Contracts\View\View; use Illuminate\Contracts\View\View;
use App\Classes\LDAP\Attribute\Binary; use App\Classes\LDAP\Attribute\Binary;
use App\Ldap\Entry; use App\Classes\Template;
use App\Traits\MD5Updates; use App\Traits\MD5Updates;
/** /**
@ -15,7 +15,7 @@ final class JpegPhoto extends Binary
{ {
use MD5Updates; use MD5Updates;
public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,bool $updated=FALSE,?string $template=NULL): View public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,bool $updated=FALSE,?Template $template=NULL): View
{ {
return view('components.attribute.binary.jpegphoto') return view('components.attribute.binary.jpegphoto')
->with('o',$this) ->with('o',$this)

View File

@ -2,9 +2,6 @@
namespace App\Classes\LDAP\Attribute; namespace App\Classes\LDAP\Attribute;
use Carbon\Carbon;
use Illuminate\Support\Arr;
use App\Classes\LDAP\Attribute; use App\Classes\LDAP\Attribute;
use App\Traits\MD5Updates; use App\Traits\MD5Updates;

View File

@ -3,7 +3,6 @@
namespace App\Classes\LDAP\Attribute; namespace App\Classes\LDAP\Attribute;
use Illuminate\Support\Arr; use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Log;
use App\Classes\LDAP\Attribute; use App\Classes\LDAP\Attribute;

View File

@ -5,14 +5,14 @@ namespace App\Classes\LDAP\Attribute\Internal;
use Illuminate\Contracts\View\View; use Illuminate\Contracts\View\View;
use App\Classes\LDAP\Attribute\Internal; use App\Classes\LDAP\Attribute\Internal;
use App\Ldap\Entry; use App\Classes\Template;
/** /**
* Represents an attribute whose values are timestamps * Represents an attribute whose values are timestamps
*/ */
final class Timestamp extends Internal final class Timestamp extends Internal
{ {
public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,bool $updated=FALSE,?string $template=NULL): View public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,bool $updated=FALSE,?Template $template=NULL): View
{ {
// @note Internal attributes cannot be edited // @note Internal attributes cannot be edited
return view('components.attribute.internal.timestamp') return view('components.attribute.internal.timestamp')

View File

@ -5,7 +5,7 @@ namespace App\Classes\LDAP\Attribute;
use Illuminate\Contracts\View\View; use Illuminate\Contracts\View\View;
use App\Classes\LDAP\Attribute; use App\Classes\LDAP\Attribute;
use App\Ldap\Entry; use App\Classes\Template;
use App\Traits\MD5Updates; use App\Traits\MD5Updates;
/** /**
@ -17,7 +17,7 @@ final class KrbPrincipalKey extends Attribute
protected(set) bool $no_attr_tags = TRUE; protected(set) bool $no_attr_tags = TRUE;
public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,bool $updated=FALSE,?string $template=NULL): View public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,bool $updated=FALSE,?Template $template=NULL): View
{ {
return view('components.attribute.krbprincipalkey') return view('components.attribute.krbprincipalkey')
->with('o',$this) ->with('o',$this)

View File

@ -6,7 +6,7 @@ use Illuminate\Contracts\View\View;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use App\Classes\LDAP\Attribute; use App\Classes\LDAP\Attribute;
use App\Ldap\Entry; use App\Classes\Template;
/** /**
* Represents an attribute whose value is a Kerberos Ticket Flag * Represents an attribute whose value is a Kerberos Ticket Flag
@ -50,7 +50,7 @@ final class KrbTicketFlags extends Attribute
return $helpers; return $helpers;
} }
public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,bool $updated=FALSE,?string $template=NULL): View public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,bool $updated=FALSE,?Template $template=NULL): View
{ {
return view('components.attribute.krbticketflags') return view('components.attribute.krbticketflags')
->with('o',$this) ->with('o',$this)

View File

@ -6,7 +6,7 @@ use Illuminate\Contracts\View\View;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use App\Classes\LDAP\Attribute; use App\Classes\LDAP\Attribute;
use App\Ldap\Entry; use App\Classes\Template;
/** /**
* Represents an ObjectClass Attribute * Represents an ObjectClass Attribute
@ -70,7 +70,7 @@ final class ObjectClass extends Attribute
->contains($value); ->contains($value);
} }
public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,bool $updated=FALSE,?string $template=NULL): View public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,bool $updated=FALSE,?Template $template=NULL): View
{ {
return view('components.attribute.objectclass') return view('components.attribute.objectclass')
->with('o',$this) ->with('o',$this)

View File

@ -7,7 +7,7 @@ use Illuminate\Support\Arr;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use App\Classes\LDAP\Attribute; use App\Classes\LDAP\Attribute;
use App\Ldap\Entry; use App\Classes\Template;
use App\Traits\MD5Updates; use App\Traits\MD5Updates;
/** /**
@ -80,7 +80,7 @@ final class Password extends Attribute
return ($helpers=static::helpers())->has($id) ? new ($helpers->get($id)) : NULL; return ($helpers=static::helpers())->has($id) ? new ($helpers->get($id)) : NULL;
} }
public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,bool $updated=FALSE,?string $template=NULL): View public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,bool $updated=FALSE,?Template $template=NULL): View
{ {
return view('components.attribute.password') return view('components.attribute.password')
->with('o',$this) ->with('o',$this)

View File

@ -6,7 +6,7 @@ use Illuminate\Contracts\View\View;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use App\Classes\LDAP\Attribute; use App\Classes\LDAP\Attribute;
use App\Ldap\Entry; use App\Classes\Template;
/** /**
* Represents the RDN for an Entry * Represents the RDN for an Entry
@ -35,7 +35,7 @@ final class RDN extends Attribute
]); ]);
} }
public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,bool $updated=FALSE,?string $template=NULL): View public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,bool $updated=FALSE,?Template $template=NULL): View
{ {
return view('components.attribute.rdn') return view('components.attribute.rdn')
->with('o',$this); ->with('o',$this);

View File

@ -2,12 +2,10 @@
namespace App\Classes\LDAP\Attribute; namespace App\Classes\LDAP\Attribute;
use Illuminate\Contracts\View\View;
use Illuminate\Support\Arr; use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Cache;
use App\Classes\LDAP\Attribute; use App\Classes\LDAP\Attribute;
use App\Ldap\Entry;
/** /**
* Represents an attribute whose values are schema related * Represents an attribute whose values are schema related

View File

@ -5,14 +5,14 @@ namespace App\Classes\LDAP\Attribute\Schema;
use Illuminate\Contracts\View\View; use Illuminate\Contracts\View\View;
use App\Classes\LDAP\Attribute\Schema; use App\Classes\LDAP\Attribute\Schema;
use App\Ldap\Entry; use App\Classes\Template;
/** /**
* Represents a Generic Schema Attribute * Represents a Generic Schema Attribute
*/ */
class Generic extends Schema class Generic extends Schema
{ {
public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,bool $updated=FALSE,?string $template=NULL): View public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,bool $updated=FALSE,?Template $template=NULL): View
{ {
// @note Schema attributes cannot be edited // @note Schema attributes cannot be edited
return view('components.attribute.schema.generic') return view('components.attribute.schema.generic')

View File

@ -5,7 +5,7 @@ namespace App\Classes\LDAP\Attribute\Schema;
use Illuminate\Contracts\View\View; use Illuminate\Contracts\View\View;
use App\Classes\LDAP\Attribute\Schema; use App\Classes\LDAP\Attribute\Schema;
use App\Ldap\Entry; use App\Classes\Template;
/** /**
* Represents a Mechanisms Attribute * Represents a Mechanisms Attribute
@ -34,7 +34,7 @@ final class Mechanisms extends Schema
return parent::_get(config_path('ldap_supported_saslmechanisms.txt'),$string,$key); return parent::_get(config_path('ldap_supported_saslmechanisms.txt'),$string,$key);
} }
public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,bool $updated=FALSE,?string $template=NULL): View public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,bool $updated=FALSE,?Template $template=NULL): View
{ {
// @note Schema attributes cannot be edited // @note Schema attributes cannot be edited
return view('components.attribute.schema.mechanisms') return view('components.attribute.schema.mechanisms')

View File

@ -5,7 +5,7 @@ namespace App\Classes\LDAP\Attribute\Schema;
use Illuminate\Contracts\View\View; use Illuminate\Contracts\View\View;
use App\Classes\LDAP\Attribute\Schema; use App\Classes\LDAP\Attribute\Schema;
use App\Ldap\Entry; use App\Classes\Template;
/** /**
* Represents an OID Attribute * Represents an OID Attribute
@ -35,7 +35,7 @@ final class OID extends Schema
return parent::_get(config_path('ldap_supported_oids.txt'),$string,$key); return parent::_get(config_path('ldap_supported_oids.txt'),$string,$key);
} }
public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,bool $updated=FALSE,?string $template=NULL): View public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,bool $updated=FALSE,?Template $template=NULL): View
{ {
// @note Schema attributes cannot be edited // @note Schema attributes cannot be edited
return view('components.attribute.schema.oid') return view('components.attribute.schema.oid')

View File

@ -20,6 +20,8 @@ class Template
$this->file = $file; $this->file = $file;
try { try {
// @todo Load in the proper attribute objects and objectclass objects
// @todo Make sure we have a structural objectclass, or make the template invalid
$this->template = json_decode($td->get($file),null,512,JSON_OBJECT_AS_ARRAY|JSON_THROW_ON_ERROR); $this->template = json_decode($td->get($file),null,512,JSON_OBJECT_AS_ARRAY|JSON_THROW_ON_ERROR);
} catch (\JsonException $e) { } catch (\JsonException $e) {
@ -46,9 +48,4 @@ class Template
{ {
return array_key_exists($key,$this->template); return array_key_exists($key,$this->template);
} }
public function __toString(): string
{
return $this->invalid ? '' : Arr::get($this->template,'title','No Template Name');
}
} }

View File

@ -6,6 +6,7 @@ use Illuminate\Contracts\View\View;
use Illuminate\View\Component; use Illuminate\View\Component;
use App\Classes\LDAP\Attribute as LDAPAttribute; use App\Classes\LDAP\Attribute as LDAPAttribute;
use App\Classes\Template;
class Attribute extends Component class Attribute extends Component
{ {
@ -14,12 +15,12 @@ class Attribute extends Component
public bool $new; public bool $new;
public bool $old; public bool $old;
public bool $updated; public bool $updated;
public bool $template; public ?Template $template;
/** /**
* Create a new component instance. * Create a new component instance.
*/ */
public function __construct(?LDAPAttribute $o,bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,bool $updated=FALSE,string $template=NULL) public function __construct(?LDAPAttribute $o,bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,bool $updated=FALSE,?Template $template=NULL)
{ {
$this->o = $o; $this->o = $o;
$this->edit = $edit; $this->edit = $edit;
@ -38,7 +39,12 @@ class Attribute extends Component
{ {
return $this->o return $this->o
? $this->o ? $this->o
->render(edit: $this->edit,old: $this->old,new: $this->new,template: $this->template,updated: $this->updated) ->render(
edit: $this->edit,
old: $this->old,
new: $this->new,
updated: $this->updated,
template: $this->template)
: __('Unknown'); : __('Unknown');
} }
} }

View File

@ -4,7 +4,7 @@
@foreach(($o->tagValues($langtag)->count() ? $o->tagValues($langtag) : [$langtag => NULL]) as $key => $value) @foreach(($o->tagValues($langtag)->count() ? $o->tagValues($langtag) : [$langtag => NULL]) as $key => $value)
@if($edit) @if($edit)
<div class="input-group has-validation"> <div class="input-group has-validation">
<x-form.select id="userpassword_hash_{{$loop->index}}{{$template ?? ''}}" name="userpassword_hash[{{ $langtag }}][]" :value="$o->hash($new ? '' : ($value ?? ''))->id()" :options="$helpers" allowclear="false" :disabled="! $new"/> <x-form.select id="userpassword_hash_{{$loop->index}}{{$template?->name ?? ''}}" name="userpassword_hash[{{ $langtag }}][]" :value="$o->hash($new ? '' : ($value ?? ''))->id()" :options="$helpers" allowclear="false" :disabled="! $new"/>
<input type="password" @class(['form-control','is-invalid'=>($e=$errors->get($o->name_lc.'.'.$langtag.'.'.$loop->index)),'mb-1','border-focus'=>! $o->tagValuesOld($langtag)->contains($value),'bg-success-subtle'=>$updated]) name="{{ $o->name_lc }}[{{ $langtag }}][]" value="{{ Arr::get(old($o->name_lc),$langtag.'.'.$loop->index,$value ? md5($value) : '') }}" @readonly(! $new)> <input type="password" @class(['form-control','is-invalid'=>($e=$errors->get($o->name_lc.'.'.$langtag.'.'.$loop->index)),'mb-1','border-focus'=>! $o->tagValuesOld($langtag)->contains($value),'bg-success-subtle'=>$updated]) name="{{ $o->name_lc }}[{{ $langtag }}][]" value="{{ Arr::get(old($o->name_lc),$langtag.'.'.$loop->index,$value ? md5($value) : '') }}" @readonly(! $new)>
<div class="invalid-feedback pb-2"> <div class="invalid-feedback pb-2">

View File

@ -9,7 +9,7 @@
@php($up=(session()->pull('updated') ?: collect())) @php($up=(session()->pull('updated') ?: collect()))
@foreach($o->getVisibleAttributes()->filter(fn($item)=>$template->attributes->map('strtolower')->contains($item->name_lc)) as $ao) @foreach($o->getVisibleAttributes()->filter(fn($item)=>$template->attributes->map('strtolower')->contains($item->name_lc)) as $ao)
<x-attribute-type :o="$ao" :edit="TRUE" :new="FALSE" :template="$template->name" :updated="$up->contains($ao->name_lc)"/> <x-attribute-type :o="$ao" :edit="TRUE" :new="FALSE" :template="$template" :updated="$up->contains($ao->name_lc)"/>
@endforeach @endforeach
</div> </div>
</div> </div>

View File

@ -66,7 +66,7 @@
<x-attribute-type :o="$o->getObject('rdn')" :edit="TRUE" :new="FALSE" :updated="FALSE"/> <x-attribute-type :o="$o->getObject('rdn')" :edit="TRUE" :new="FALSE" :updated="FALSE"/>
@foreach($o->getVisibleAttributes() as $ao) @foreach($o->getVisibleAttributes() as $ao)
<x-attribute-type :o="$ao" :edit="TRUE" :new="FALSE" :updated="FALSE"/> <x-attribute-type :o="$ao" :edit="TRUE" :new="FALSE" :template="$template" :updated="FALSE"/>
@endforeach @endforeach
@if(! $template) @if(! $template)

View File

@ -75,8 +75,8 @@
<div class="d-flex justify-content-center"> <div class="d-flex justify-content-center">
<div role="group" class="btn-group btn-group-sm nav pb-3"> <div role="group" class="btn-group btn-group-sm nav pb-3">
<!-- If we have templates that cover this entry --> <!-- If we have templates that cover this entry -->
@foreach($o->templates as $template => $name) @foreach($o->templates as $template)
<span data-bs-toggle="tab" href="#template-{{$template}}" @class(['btn','btn-outline-focus','active'=>$loop->index === 0])><i class="fa fa-fw pe-2 {{ $o->template($template)->icon }}"></i> {{ $name }}</span> <span data-bs-toggle="tab" href="#template-{{ $template->name }}" @class(['btn','btn-outline-focus','active'=>$loop->index === 0])><i class="fa fa-fw pe-2 {{ $template->icon }}"></i> {{ $template->title }}</span>
@endforeach @endforeach
@if($o->templates->count()) @if($o->templates->count())
<span data-bs-toggle="tab" href="#template-default" @class(['btn','btn-outline-focus','p-1','active'=>(! $o->templates->count())])>{{ __('LDAP Entry') }}</span> <span data-bs-toggle="tab" href="#template-default" @class(['btn','btn-outline-focus','p-1','active'=>(! $o->templates->count())])>{{ __('LDAP Entry') }}</span>
@ -85,9 +85,9 @@
</div> </div>
<div class="tab-content"> <div class="tab-content">
@foreach($o->templates as $template => $name) @foreach($o->templates as $template)
<div @class(['tab-pane','active'=>$loop->index === 0]) id="template-{{$template}}" role="tabpanel"> <div @class(['tab-pane','active'=>$loop->index === 0]) id="template-{{ $template->name }}" role="tabpanel">
@include('fragment.template.dn',['template'=>$o->template($template)]) @include('fragment.template.dn',['template'=>$template])
</div> </div>
@endforeach @endforeach