diff --git a/app/Classes/LDAP/Attribute.php b/app/Classes/LDAP/Attribute.php index 666fe43c..115eff09 100644 --- a/app/Classes/LDAP/Attribute.php +++ b/app/Classes/LDAP/Attribute.php @@ -19,6 +19,7 @@ class Attribute implements \Countable, \ArrayAccess, \Iterator // Is this attribute an internal attribute protected(set) bool $is_internal = FALSE; + protected(set) bool $no_attr_tags = FALSE; // MIN/MAX number of values protected(set) int $min_values_count = 0; @@ -34,9 +35,9 @@ class Attribute implements \Countable, \ArrayAccess, \Iterator // The DN this object is in protected(set) string $dn; // The old values for this attribute - helps with isDirty() to determine if there is an update pending - protected(set) Collection $values_old; + private Collection $_values_old; // Current Values - protected Collection $values; + private Collection $_values; // The objectclasses of the entry that has this attribute protected(set) Collection $oc; @@ -153,7 +154,10 @@ class Attribute implements \Countable, \ArrayAccess, \Iterator // Used in Object Classes 'used_in' => $this->schema?->used_in_object_classes ?: collect(), // The current attribute values - 'values' => $this->values, + 'values' => $this->no_attr_tags ? collect($this->_values->first()) : $this->_values, + // The original attribute values + 'values_old' => $this->no_attr_tags ? collect($this->_values_old->first()) : $this->_values_old, + default => throw new \Exception('Unknown key:' . $key), }; @@ -163,8 +167,11 @@ class Attribute implements \Countable, \ArrayAccess, \Iterator { switch ($key) { case 'values': - if (is_null($values)) throw new \Exception('values is null?'); - $this->values = $values; + $this->_values = $values; + break; + + case 'values_old': + $this->_values_old = $values; break; default: diff --git a/app/Classes/LDAP/Attribute/Factory.php b/app/Classes/LDAP/Attribute/Factory.php index f4841a15..3d23fc9e 100644 --- a/app/Classes/LDAP/Attribute/Factory.php +++ b/app/Classes/LDAP/Attribute/Factory.php @@ -28,6 +28,11 @@ class Factory 'entrydn' => Internal\DN::class, 'entryuuid' => Internal\UUID::class, 'etag' => Internal\Etag::class, + 'krblastfailedauth' => Attribute\NoAttrTags\Generic::class, + 'krblastpwdchange' => Attribute\NoAttrTags\Generic::class, + 'krblastsuccessfulauth' => Attribute\NoAttrTags\Generic::class, + 'krbpasswordexpiration' => Attribute\NoAttrTags\Generic::class, + 'krbloginfailedcount' => Attribute\NoAttrTags\Generic::class, 'krbprincipalkey' => KrbPrincipalKey::class, 'krbticketflags' => KrbTicketFlags::class, 'gidnumber' => GidNumber::class, diff --git a/app/Classes/LDAP/Attribute/GidNumber.php b/app/Classes/LDAP/Attribute/GidNumber.php index b2a05a35..c6ad0bd1 100644 --- a/app/Classes/LDAP/Attribute/GidNumber.php +++ b/app/Classes/LDAP/Attribute/GidNumber.php @@ -9,4 +9,5 @@ use App\Classes\LDAP\Attribute; */ final class GidNumber extends Attribute { + protected(set) bool $no_attr_tags = FALSE; } \ No newline at end of file diff --git a/app/Classes/LDAP/Attribute/Internal.php b/app/Classes/LDAP/Attribute/Internal.php index 6db070d5..d6d99097 100644 --- a/app/Classes/LDAP/Attribute/Internal.php +++ b/app/Classes/LDAP/Attribute/Internal.php @@ -12,15 +12,7 @@ use App\Classes\LDAP\Attribute; abstract class Internal extends Attribute { protected(set) bool $is_internal = TRUE; - - public function __get(string $key): mixed - { - return match ($key) { - // Internal items shouldnt have language tags, so our values should only have 1 key - 'values'=>collect($this->values->first()), - default => parent::__get($key), - }; - } + protected(set) bool $no_attr_tags = TRUE; public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE): View { diff --git a/app/Classes/LDAP/Attribute/KrbPrincipalKey.php b/app/Classes/LDAP/Attribute/KrbPrincipalKey.php index a68acb2d..1f7d6e9c 100644 --- a/app/Classes/LDAP/Attribute/KrbPrincipalKey.php +++ b/app/Classes/LDAP/Attribute/KrbPrincipalKey.php @@ -15,6 +15,8 @@ final class KrbPrincipalKey extends Attribute { use MD5Updates; + protected(set) bool $no_attr_tags = TRUE; + public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE): View { return view('components.attribute.krbprincipalkey') diff --git a/app/Classes/LDAP/Attribute/KrbTicketFlags.php b/app/Classes/LDAP/Attribute/KrbTicketFlags.php index e52a0bbb..f25df3cb 100644 --- a/app/Classes/LDAP/Attribute/KrbTicketFlags.php +++ b/app/Classes/LDAP/Attribute/KrbTicketFlags.php @@ -13,6 +13,8 @@ use Illuminate\Support\Collection; */ final class KrbTicketFlags extends Attribute { + protected(set) bool $no_attr_tags = TRUE; + private const DISALLOW_POSTDATED = 0x00000001; private const DISALLOW_FORWARDABLE = 0x00000002; private const DISALLOW_TGT_BASED = 0x00000004; diff --git a/app/Classes/LDAP/Attribute/NoAttrTags/Generic.php b/app/Classes/LDAP/Attribute/NoAttrTags/Generic.php new file mode 100644 index 00000000..52871e0b --- /dev/null +++ b/app/Classes/LDAP/Attribute/NoAttrTags/Generic.php @@ -0,0 +1,13 @@ +<?php + +namespace App\Classes\LDAP\Attribute\NoAttrTags; + +use App\Classes\LDAP\Attribute; + +/** + * Represents an Attribute that doesnt have Lang Tags + */ +class Generic extends Attribute +{ + protected(set) bool $no_attr_tags = TRUE; +} \ No newline at end of file diff --git a/app/Classes/LDAP/Attribute/ObjectClass.php b/app/Classes/LDAP/Attribute/ObjectClass.php index 959429b3..50adcba7 100644 --- a/app/Classes/LDAP/Attribute/ObjectClass.php +++ b/app/Classes/LDAP/Attribute/ObjectClass.php @@ -12,6 +12,8 @@ use App\Classes\LDAP\Attribute; */ final class ObjectClass extends Attribute { + protected(set) bool $no_attr_tags = TRUE; + // The schema ObjectClasses for this objectclass of a DN protected Collection $oc_schema; @@ -21,7 +23,7 @@ final class ObjectClass extends Attribute * @param string $dn DN this attribute is used in * @param string $name Name of the attribute * @param array $values Current Values - * @param array $oc The objectclasses that the DN of this attribute has + * @param array $oc The objectclasses that the DN of this attribute has (ignored for objectclasses) */ public function __construct(string $dn,string $name,array $values,array $oc=[]) { @@ -29,7 +31,7 @@ final class ObjectClass extends Attribute $this->oc_schema = config('server') ->schema('objectclasses') - ->filter(fn($item)=>$this->values->merge($this->values_old)->unique()->contains($item->name)); + ->filter(fn($item)=>$this->values_old->contains($item->name)); } public function __get(string $key): mixed diff --git a/app/Classes/LDAP/Attribute/Password.php b/app/Classes/LDAP/Attribute/Password.php index d66af252..df150c0e 100644 --- a/app/Classes/LDAP/Attribute/Password.php +++ b/app/Classes/LDAP/Attribute/Password.php @@ -15,6 +15,9 @@ use App\Traits\MD5Updates; final class Password extends Attribute { use MD5Updates; + + protected(set) bool $no_attr_tags = TRUE; + private const password_helpers = 'Classes/LDAP/Attribute/Password'; public const commands = 'App\\Classes\\LDAP\\Attribute\\Password\\'; diff --git a/app/Classes/LDAP/Attribute/Schema.php b/app/Classes/LDAP/Attribute/Schema.php index c1f7f48a..b971784a 100644 --- a/app/Classes/LDAP/Attribute/Schema.php +++ b/app/Classes/LDAP/Attribute/Schema.php @@ -14,6 +14,7 @@ use App\Classes\LDAP\Attribute; abstract class Schema extends Attribute { protected bool $internal = TRUE; + protected(set) bool $no_attr_tags = TRUE; protected static function _get(string $filename,string $string,string $key): ?string { @@ -52,15 +53,6 @@ abstract class Schema extends Attribute __('No description available, can you help with one?')); } - public function __get(string $key): mixed - { - return match ($key) { - // Schema items shouldnt have language tags, so our values should only have 1 key - 'values'=>collect($this->values->first()), - default => parent::__get($key), - }; - } - public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE): View { // @note Schema attributes cannot be edited diff --git a/app/Ldap/Entry.php b/app/Ldap/Entry.php index 2cdd05ba..a4e1ac47 100644 --- a/app/Ldap/Entry.php +++ b/app/Ldap/Entry.php @@ -282,6 +282,7 @@ class Entry extends Model public function getLangTags(): Collection { return $this->getObjects() + ->filter(fn($item)=>! $item->no_attr_tags) ->map(fn($item)=>$item ->values ->keys() @@ -336,6 +337,7 @@ class Entry extends Model public function getOtherTags(): Collection { return $this->getObjects() + ->filter(fn($item)=>! $item->no_attr_tags) ->map(fn($item)=>$item ->values ->keys() diff --git a/resources/views/components/attribute.blade.php b/resources/views/components/attribute.blade.php index ff942c7a..db84c49c 100644 --- a/resources/views/components/attribute.blade.php +++ b/resources/views/components/attribute.blade.php @@ -1,19 +1,31 @@ <!-- $o=Attribute::class --> <x-attribute.layout :edit="$edit ?? FALSE" :new="$new ?? FALSE" :o="$o"> - @foreach(old($o->name_lc,($new ?? FALSE) ? [NULL] : $o->values) as $value) - @if (($edit ?? FALSE) && ! $o->is_rdn) - <div class="input-group has-validation"> - <input type="text" @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="{{ $value }}" placeholder="{{ ! is_null($x=Arr::get($o->values,$loop->index)) ? $x : '['.__('NEW').']' }}" @readonly(! ($new ?? FALSE))> + @foreach(old($o->name_lc,($new ?? FALSE) ? [NULL] : $o->values) as $tag=>$tagvalues) + <div class="row p-2 border rounded"> + <div class="col-2"> + {{ $tag }} + </div> + <div class="col-10"> + <div class="row"> + <div class="col-12"> + @foreach($tagvalues as $value) + @if(($edit ?? FALSE) && ! $o->is_rdn) + <div class="input-group has-validation"> + <input type="text" @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="{{ $value }}" placeholder="{{ ! is_null($x=Arr::get($o->values,$loop->index)) ? $x : '['.__('NEW').']' }}" @readonly(! ($new ?? FALSE))> - <div class="invalid-feedback pb-2"> - @if($e) - {{ join('|',$e) }} - @endif + <div class="invalid-feedback pb-2"> + @if($e) + {{ join('|',$e) }} + @endif + </div> + </div> + @else + {{ $value }} + @endif + @endforeach + </div> </div> </div> - - @else - {{ $value }} - @endif + </div> @endforeach </x-attribute.layout> \ No newline at end of file diff --git a/resources/views/components/attribute/krblastfailedauth.blade.php b/resources/views/components/attribute/krblastfailedauth.blade.php index 7caa074e..afe6653c 100644 --- a/resources/views/components/attribute/krblastfailedauth.blade.php +++ b/resources/views/components/attribute/krblastfailedauth.blade.php @@ -1,8 +1,2 @@ -<!-- $o=Attribute::class --> -<x-attribute.layout :edit="false" :new="false" :detail="true" :o="$o"> - @foreach(old($o->name_lc,($new ?? FALSE) ? [NULL] : $o->values) as $value) - <div class="input-group"> - <input type="text" @class(['form-control','mb-1']) name="{{ $o->name_lc }}[]" value="{{ \Carbon\Carbon::createFromTimestamp(strtotime($value))->format(config('pla.datetime_format','Y-m-d H:i:s')) }}" @disabled(true)> - </div> - @endforeach -</x-attribute.layout> +<!-- $o=NoAttrTags/Generic::class --> +@include('components.form.disabled.datetime') diff --git a/resources/views/components/attribute/krblastpwdchange.blade.php b/resources/views/components/attribute/krblastpwdchange.blade.php index 7d7468bf..beddcb75 100644 --- a/resources/views/components/attribute/krblastpwdchange.blade.php +++ b/resources/views/components/attribute/krblastpwdchange.blade.php @@ -1 +1,2 @@ -@include('components.attribute.krblastfailedauth') \ No newline at end of file +<!-- $o=NoAttrTags/Generic::class --> +@include('components.form.disabled.datetime') \ No newline at end of file diff --git a/resources/views/components/attribute/krblastsuccessfulauth.blade.php b/resources/views/components/attribute/krblastsuccessfulauth.blade.php index 7d7468bf..beddcb75 100644 --- a/resources/views/components/attribute/krblastsuccessfulauth.blade.php +++ b/resources/views/components/attribute/krblastsuccessfulauth.blade.php @@ -1 +1,2 @@ -@include('components.attribute.krblastfailedauth') \ No newline at end of file +<!-- $o=NoAttrTags/Generic::class --> +@include('components.form.disabled.datetime') \ No newline at end of file diff --git a/resources/views/components/attribute/krbloginfailedcount.blade.php b/resources/views/components/attribute/krbloginfailedcount.blade.php index 57f65b93..f5cb05af 100644 --- a/resources/views/components/attribute/krbloginfailedcount.blade.php +++ b/resources/views/components/attribute/krbloginfailedcount.blade.php @@ -1,8 +1,2 @@ -<!-- $o=Attribute::class --> -<x-attribute.layout :edit="false" :new="false" :detail="true" :o="$o"> - @foreach(old($o->name_lc,($new ?? FALSE) ? [NULL] : $o->values) as $value) - <div class="input-group"> - <input type="text" @class(['form-control','mb-1']) name="{{ $o->name_lc }}[]" value="{{ $value }}" @disabled(true)> - </div> - @endforeach -</x-attribute.layout> +<!-- $o=NoAttrTags/Generic::class --> +@include('components.form.disabled.input') \ No newline at end of file diff --git a/resources/views/components/attribute/krbpasswordexpiration.blade.php b/resources/views/components/attribute/krbpasswordexpiration.blade.php index 7d7468bf..beddcb75 100644 --- a/resources/views/components/attribute/krbpasswordexpiration.blade.php +++ b/resources/views/components/attribute/krbpasswordexpiration.blade.php @@ -1 +1,2 @@ -@include('components.attribute.krblastfailedauth') \ No newline at end of file +<!-- $o=NoAttrTags/Generic::class --> +@include('components.form.disabled.datetime') \ No newline at end of file diff --git a/resources/views/components/attribute/krbprincipalkey.blade.php b/resources/views/components/attribute/krbprincipalkey.blade.php index 3c89d26e..1f7d0fee 100644 --- a/resources/views/components/attribute/krbprincipalkey.blade.php +++ b/resources/views/components/attribute/krbprincipalkey.blade.php @@ -1,5 +1,5 @@ <!-- @todo We are not handling redirect backs yet with updated passwords --> -<!-- $o=Password::class --> +<!-- $o=KrbPrincipleKey::class --> <x-attribute.layout :edit="$edit ?? FALSE" :new="$new ?? FALSE" :o="$o"> @foreach($o->values_old as $value) @if($edit) diff --git a/resources/views/components/attribute/krbticketflags.blade.php b/resources/views/components/attribute/krbticketflags.blade.php index 0b246f08..bec368e7 100644 --- a/resources/views/components/attribute/krbticketflags.blade.php +++ b/resources/views/components/attribute/krbticketflags.blade.php @@ -1,29 +1,23 @@ <!-- $o=KrbTicketFlags::class --> <x-attribute.layout :edit="$edit ?? FALSE" :new="$new ?? FALSE" :o="$o"> - <!-- krbticketflags cannot handle multivalue tags --> - @if($o->values->keys()->count() <= 1) - @foreach((count($o->values->first()) ? $o->values->first() : ($new ? [0] : NULL)) as $value) - @if($edit) - <div id="32"></div> - <div id="16"></div> + @foreach(($o->values->count() ? $o->values : ($new ? [0] : NULL)) as $value) + @if($edit) + <div id="32"></div> + <div id="16"></div> - <div class="input-group has-validation mb-3"> - <input type="hidden" @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="{{ $value }}" @readonly(true)> + <div class="input-group has-validation mb-3"> + <input type="hidden" @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="{{ $value }}" @readonly(true)> - <div class="invalid-feedback pb-2"> - @if($e) - {{ join('|',$e) }} - @endif - </div> + <div class="invalid-feedback pb-2"> + @if($e) + {{ join('|',$e) }} + @endif </div> - @else - {{ $value }} - @endif - @endforeach - - @else - <x-alert.attribute_tags_cant_manage :tags="$o->values->keys()"/> - @endif + </div> + @else + {{ $value }} + @endif + @endforeach </x-attribute.layout> @section($o->name_lc.'-scripts') diff --git a/resources/views/components/attribute/objectclass.blade.php b/resources/views/components/attribute/objectclass.blade.php index d87c999e..22b9f7f4 100644 --- a/resources/views/components/attribute/objectclass.blade.php +++ b/resources/views/components/attribute/objectclass.blade.php @@ -1,7 +1,7 @@ <!-- $o=Attribute::class --> <x-attribute.layout :edit="$edit" :new="$new" :o="$o"> @foreach(old($o->name_lc,$o->values) as $value) - @if ($edit) + @if($edit) <x-attribute.widget.objectclass :o="$o" :edit="$edit" :new="$new" :loop="$loop" :value="$value"/> @else {{ $value }} diff --git a/resources/views/components/form/disabled/datetime.blade.php b/resources/views/components/form/disabled/datetime.blade.php new file mode 100644 index 00000000..0d667ee2 --- /dev/null +++ b/resources/views/components/form/disabled/datetime.blade.php @@ -0,0 +1,8 @@ +<!-- $o=Attribute::class --> +<x-attribute.layout :edit="false" :new="false" :detail="true" :o="$o"> + @foreach(old($o->name_lc,($new ?? FALSE) ? [NULL] : $o->values) as $value) + <div class="input-group"> + <input type="text" @class(['form-control','mb-1']) name="{{ $o->name_lc }}[]" value="{{ \Carbon\Carbon::createFromTimestamp(strtotime($value))->format(config('pla.datetime_format','Y-m-d H:i:s')) }}" @disabled(true)> + </div> + @endforeach +</x-attribute.layout> \ No newline at end of file diff --git a/resources/views/components/form/disabled/input.blade.php b/resources/views/components/form/disabled/input.blade.php new file mode 100644 index 00000000..53706589 --- /dev/null +++ b/resources/views/components/form/disabled/input.blade.php @@ -0,0 +1,8 @@ +<!-- $o=Attribute::class --> +<x-attribute.layout :edit="false" :new="false" :detail="true" :o="$o"> + @foreach(old($o->name_lc,($new ?? FALSE) ? [NULL] : $o->values) as $value) + <div class="input-group"> + <input type="text" @class(['form-control','mb-1']) name="{{ $o->name_lc }}[]" value="{{ $value }}" @disabled(true)> + </div> + @endforeach +</x-attribute.layout> \ No newline at end of file