diff --git a/.gitea/workflows/build_docker.yaml b/.gitea/workflows/build_docker.yaml index 3e38d95f..375e9d1e 100644 --- a/.gitea/workflows/build_docker.yaml +++ b/.gitea/workflows/build_docker.yaml @@ -3,7 +3,7 @@ run-name: ${{ gitea.actor }} Building Docker Image 🐳 on: [push] env: DOCKER_HOST: tcp://127.0.0.1:2375 - ASSETS: 10eca55 + ASSETS: 3fcb8707 jobs: test: diff --git a/app/Classes/LDAP/Attribute.php b/app/Classes/LDAP/Attribute.php index 3f502e40..1459f068 100644 --- a/app/Classes/LDAP/Attribute.php +++ b/app/Classes/LDAP/Attribute.php @@ -148,6 +148,13 @@ class Attribute implements \Countable, \ArrayAccess 'description' => $this->schema ? $this->schema->{$key} : NULL, // Attribute hints 'hints' => $this->hints(), + // Attribute language tags + 'langtags' => ($this->no_attr_tags || (! $this->_values->count())) + ? collect(Entry::TAG_NOTAG) + : $this->_values + ->keys() + ->filter(fn($item)=>($item === Entry::TAG_NOTAG) || preg_match(sprintf('/%s;?/',Entry::TAG_CHARS_LANG),$item)) + ->sortBy(fn($item)=>($item === Entry::TAG_NOTAG) ? NULL : $item), // Can this attribute be edited 'is_editable' => $this->schema ? $this->schema->{$key} : NULL, // Is this an internal attribute @@ -198,17 +205,23 @@ class Attribute implements \Countable, \ArrayAccess public function count(): int { - return $this->_values->dot()->count(); + return $this->_values + ->dot() + ->count(); } public function offsetExists(mixed $offset): bool { - return $this->_values->dot()->has($offset); + return $this->_values + ->dot() + ->has($offset); } public function offsetGet(mixed $offset): mixed { - return $this->_values->dot()->get($offset); + return $this->_values + ->dot() + ->get($offset); } public function offsetSet(mixed $offset, mixed $value): void @@ -315,11 +328,10 @@ class Attribute implements \Countable, \ArrayAccess * @param bool $edit Render an edit form * @param bool $old Use old value * @param bool $new Enable adding values - * @param string $langtag Langtag to use when rendering these attribute values * @param bool $updated Has the entry been updated (uses rendering highlights)) * @return View */ - public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,string $langtag=Entry::TAG_NOTAG,bool $updated=FALSE): View + public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,bool $updated=FALSE): View { if ($this->is_internal) // @note Internal attributes cannot be edited @@ -340,7 +352,6 @@ class Attribute implements \Countable, \ArrayAccess ->with('edit',$edit) ->with('old',$old) ->with('new',$new) - ->with('langtag',$langtag) ->with('updated',$updated); } @@ -376,7 +387,7 @@ class Attribute implements \Countable, \ArrayAccess * * @return Collection */ - public function required(): Collection + private function required(): Collection { // If we dont have any objectclasses then we cant know if it is required return $this->oc->count() diff --git a/app/Classes/LDAP/Attribute/Binary/JpegPhoto.php b/app/Classes/LDAP/Attribute/Binary/JpegPhoto.php index 37f64aa0..65734233 100644 --- a/app/Classes/LDAP/Attribute/Binary/JpegPhoto.php +++ b/app/Classes/LDAP/Attribute/Binary/JpegPhoto.php @@ -15,14 +15,13 @@ final class JpegPhoto extends Binary { use MD5Updates; - public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,string $langtag=Entry::TAG_NOTAG,bool $updated=FALSE): View + public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,bool $updated=FALSE): View { return view('components.attribute.binary.jpegphoto') ->with('o',$this) ->with('edit',$edit) ->with('old',$old) ->with('new',$new) - ->with('langtag',$langtag) ->with('updated',$updated) ->with('f',new \finfo); } diff --git a/app/Classes/LDAP/Attribute/Internal/Timestamp.php b/app/Classes/LDAP/Attribute/Internal/Timestamp.php index 72533331..845197ef 100644 --- a/app/Classes/LDAP/Attribute/Internal/Timestamp.php +++ b/app/Classes/LDAP/Attribute/Internal/Timestamp.php @@ -12,7 +12,7 @@ use App\Ldap\Entry; */ final class Timestamp extends Internal { - public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,string $langtag=Entry::TAG_NOTAG,bool $updated=FALSE): View + public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,bool $updated=FALSE): View { // @note Internal attributes cannot be edited return view('components.attribute.internal.timestamp') diff --git a/app/Classes/LDAP/Attribute/KrbPrincipalKey.php b/app/Classes/LDAP/Attribute/KrbPrincipalKey.php index 1fb378e6..7c88b0bd 100644 --- a/app/Classes/LDAP/Attribute/KrbPrincipalKey.php +++ b/app/Classes/LDAP/Attribute/KrbPrincipalKey.php @@ -17,7 +17,7 @@ final class KrbPrincipalKey extends Attribute protected(set) bool $no_attr_tags = TRUE; - public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,string $langtag=Entry::TAG_NOTAG,bool $updated=FALSE): View + public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,bool $updated=FALSE): View { return view('components.attribute.krbprincipalkey') ->with('o',$this) diff --git a/app/Classes/LDAP/Attribute/KrbTicketFlags.php b/app/Classes/LDAP/Attribute/KrbTicketFlags.php index 6921a9d3..80b62cae 100644 --- a/app/Classes/LDAP/Attribute/KrbTicketFlags.php +++ b/app/Classes/LDAP/Attribute/KrbTicketFlags.php @@ -50,7 +50,7 @@ final class KrbTicketFlags extends Attribute return $helpers; } - public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,string $langtag=Entry::TAG_NOTAG,bool $updated=FALSE): View + public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,bool $updated=FALSE): View { return view('components.attribute.krbticketflags') ->with('o',$this) diff --git a/app/Classes/LDAP/Attribute/ObjectClass.php b/app/Classes/LDAP/Attribute/ObjectClass.php index ca179a4d..5536fb04 100644 --- a/app/Classes/LDAP/Attribute/ObjectClass.php +++ b/app/Classes/LDAP/Attribute/ObjectClass.php @@ -70,7 +70,7 @@ final class ObjectClass extends Attribute ->contains($value); } - public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,string $langtag=Entry::TAG_NOTAG,bool $updated=FALSE): View + public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,bool $updated=FALSE): View { return view('components.attribute.objectclass') ->with('o',$this) diff --git a/app/Classes/LDAP/Attribute/Password.php b/app/Classes/LDAP/Attribute/Password.php index 964a5e8b..6c7cff45 100644 --- a/app/Classes/LDAP/Attribute/Password.php +++ b/app/Classes/LDAP/Attribute/Password.php @@ -80,7 +80,7 @@ final class Password extends Attribute return ($helpers=static::helpers())->has($id) ? new ($helpers->get($id)) : NULL; } - public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,string $langtag=Entry::TAG_NOTAG,bool $updated=FALSE): View + public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,bool $updated=FALSE): View { return view('components.attribute.password') ->with('o',$this) diff --git a/app/Classes/LDAP/Attribute/RDN.php b/app/Classes/LDAP/Attribute/RDN.php index c28eb67e..64bb62f8 100644 --- a/app/Classes/LDAP/Attribute/RDN.php +++ b/app/Classes/LDAP/Attribute/RDN.php @@ -14,6 +14,9 @@ use App\Ldap\Entry; final class RDN extends Attribute { private string $base; + + protected(set) bool $no_attr_tags = TRUE; + private Collection $attrs; public function __get(string $key): mixed @@ -32,7 +35,7 @@ final class RDN extends Attribute ]); } - public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,string $langtag=Entry::TAG_NOTAG,bool $updated=FALSE): View + public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,bool $updated=FALSE): View { return view('components.attribute.rdn') ->with('o',$this); diff --git a/app/Classes/LDAP/Attribute/Schema.php b/app/Classes/LDAP/Attribute/Schema.php index 22941082..30ba55dd 100644 --- a/app/Classes/LDAP/Attribute/Schema.php +++ b/app/Classes/LDAP/Attribute/Schema.php @@ -54,7 +54,7 @@ abstract class Schema extends Attribute __('No description available, can you help with one?')); } - public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,string $langtag=Entry::TAG_NOTAG,bool $updated=FALSE): View + public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,bool $updated=FALSE): View { // @note Schema attributes cannot be edited return view('components.attribute.internal') diff --git a/app/Classes/LDAP/Attribute/Schema/Generic.php b/app/Classes/LDAP/Attribute/Schema/Generic.php index 64645d5d..bf3df008 100644 --- a/app/Classes/LDAP/Attribute/Schema/Generic.php +++ b/app/Classes/LDAP/Attribute/Schema/Generic.php @@ -12,7 +12,7 @@ use App\Ldap\Entry; */ class Generic extends Schema { - public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,string $langtag=Entry::TAG_NOTAG,bool $updated=FALSE): View + public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,bool $updated=FALSE): View { // @note Schema attributes cannot be edited return view('components.attribute.schema.generic') diff --git a/app/Classes/LDAP/Attribute/Schema/Mechanisms.php b/app/Classes/LDAP/Attribute/Schema/Mechanisms.php index 2cbf8396..be402a51 100644 --- a/app/Classes/LDAP/Attribute/Schema/Mechanisms.php +++ b/app/Classes/LDAP/Attribute/Schema/Mechanisms.php @@ -34,7 +34,7 @@ final class Mechanisms extends Schema return parent::_get(config_path('ldap_supported_saslmechanisms.txt'),$string,$key); } - public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,string $langtag=Entry::TAG_NOTAG,bool $updated=FALSE): View + public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,bool $updated=FALSE): View { // @note Schema attributes cannot be edited return view('components.attribute.schema.mechanisms') diff --git a/app/Classes/LDAP/Attribute/Schema/OID.php b/app/Classes/LDAP/Attribute/Schema/OID.php index 2b9765b0..166fd8be 100644 --- a/app/Classes/LDAP/Attribute/Schema/OID.php +++ b/app/Classes/LDAP/Attribute/Schema/OID.php @@ -35,7 +35,7 @@ final class OID extends Schema return parent::_get(config_path('ldap_supported_oids.txt'),$string,$key); } - public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,string $langtag=Entry::TAG_NOTAG,bool $updated=FALSE): View + public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,bool $updated=FALSE): View { // @note Schema attributes cannot be edited return view('components.attribute.schema.oid') diff --git a/app/Http/Controllers/HomeController.php b/app/Http/Controllers/HomeController.php index eee8c61e..aa040060 100644 --- a/app/Http/Controllers/HomeController.php +++ b/app/Http/Controllers/HomeController.php @@ -356,7 +356,9 @@ class HomeController extends Controller return Redirect::to('/') ->withInput() ->with('updated',collect($dirty) - ->map(fn($item,$key)=>$o->getObject(collect(explode(';',$key))->first()))); + ->map(fn($item,$key)=>$o->getObject(collect(explode(';',$key))->first())) + ->values() + ->unique()); } /** diff --git a/app/Ldap/Entry.php b/app/Ldap/Entry.php index f8707fa8..63243e44 100644 --- a/app/Ldap/Entry.php +++ b/app/Ldap/Entry.php @@ -21,11 +21,16 @@ use App\Exceptions\InvalidUsage; class Entry extends Model { private const TAG_CHARS = 'a-zA-Z0-9-'; - private const TAG_CHARS_LANG = 'lang-['.self::TAG_CHARS.']'; + public const LANG_TAG_PREFIX = 'lang-'; + public const TAG_CHARS_LANG = self::LANG_TAG_PREFIX.'['.self::TAG_CHARS.']+'; public const TAG_NOTAG = '_null_'; // Our Attribute objects private Collection $objects; + + // Templates that apply to this entry + private(set) Collection $templates; + // For new entries, this is the container that this entry will be stored in private string $rdnbase; @@ -34,6 +39,7 @@ class Entry extends Model public function __construct(array $attributes = []) { $this->objects = collect(); + $this->templates = collect(['default'=>__('LDAP Entry')]); parent::__construct($attributes); } @@ -308,14 +314,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() - ->filter(fn($item)=>preg_match(sprintf('/%s+;?/',self::TAG_CHARS_LANG),$item)) - ->map(fn($item)=>preg_replace('/lang-/','',$item)) - ) - ->filter(fn($item)=>$item->count()); + ->map(fn($item)=>$item->langtags); } /** @@ -373,7 +372,7 @@ class Entry extends Model $item && collect(explode(';',$item))->filter( fn($item)=> (! preg_match(sprintf('/^%s$/',self::TAG_NOTAG),$item)) - && (! preg_match(sprintf('/^%s+$/',self::TAG_CHARS_LANG),$item)) + && (! preg_match(sprintf('/^%s$/',self::TAG_CHARS_LANG),$item)) ) ->count()) ) diff --git a/app/View/Components/Attribute.php b/app/View/Components/Attribute.php index 9e7b0344..cc12c0bd 100644 --- a/app/View/Components/Attribute.php +++ b/app/View/Components/Attribute.php @@ -6,7 +6,6 @@ use Illuminate\Contracts\View\View; use Illuminate\View\Component; use App\Classes\LDAP\Attribute as LDAPAttribute; -use App\Ldap\Entry; class Attribute extends Component { @@ -14,18 +13,16 @@ class Attribute extends Component public bool $edit; public bool $new; public bool $old; - public string $langtag; /** * Create a new component instance. */ - public function __construct(?LDAPAttribute $o,bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,string $langtag=Entry::TAG_NOTAG,bool $updated=FALSE) + public function __construct(?LDAPAttribute $o,bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,bool $updated=FALSE) { $this->o = $o; $this->edit = $edit; $this->old = $old; $this->new = $new; - $this->langtag = $langtag; $this->updated = $updated; } @@ -38,7 +35,7 @@ class Attribute extends Component { return $this->o ? $this->o - ->render(edit: $this->edit,old: $this->old,new: $this->new,langtag: $this->langtag,updated: $this->updated) + ->render(edit: $this->edit,old: $this->old,new: $this->new,updated: $this->updated) : __('Unknown'); } } \ No newline at end of file diff --git a/public/css/custom.css b/public/css/custom.css index 47e325e3..0104ad4c 100644 --- a/public/css/custom.css +++ b/public/css/custom.css @@ -1,23 +1,24 @@ /** ensure our userpassword has select is next to the password input */ -attribute#userPassword .select2-container--bootstrap-5 .select2-selection { +attribute#userpassword .select2-container--bootstrap-5 .select2-selection { font-size: inherit; width: 9em; border: var(--bs-gray-500) 1px solid; background-color: #f0f0f0; } -.input-group:first-child .select2-container--bootstrap-5 .select2-selection { - border-bottom-right-radius: unset; - border-top-right-radius: unset; -} - -attribute#objectClass .input-group-end:not(input.form-control) { +/* render the structural inside the input box */ +attribute#objectclass .input-group-end:not(input.form-control) { position: absolute; right: 1em; top: 0.5em; z-index: 5; } +.input-group:first-child .select2-container--bootstrap-5 .select2-selection { + border-bottom-right-radius: unset; + border-top-right-radius: unset; +} + input.form-control.input-group-end { border-bottom-right-radius: 4px !important; border-top-right-radius: 4px !important; @@ -82,4 +83,9 @@ input.form-control.input-group-end { .page-title-wrapper .page-title-items .page-title-status .alert { font-size: 0.80em; +} + +/* Square UL items */ +ul.square { + list-style-type: square; } \ No newline at end of file diff --git a/resources/themes/architect/src/utils/_helpers.scss b/resources/themes/architect/src/utils/_helpers.scss index c25ca585..515877ce 100644 --- a/resources/themes/architect/src/utils/_helpers.scss +++ b/resources/themes/architect/src/utils/_helpers.scss @@ -90,6 +90,14 @@ font-size: 1.3rem !important; } +.font-size-xs { + font-size: .6rem !important; +} + +.font-size-sm { + font-size: .8rem !important; +} + .font-size-md { font-size: .9rem !important; } diff --git a/resources/themes/architect/views/layouts/partials/topmenu.blade.php b/resources/themes/architect/views/layouts/partials/topmenu.blade.php index 8b27d7cd..04d6dde9 100644 --- a/resources/themes/architect/views/layouts/partials/topmenu.blade.php +++ b/resources/themes/architect/views/layouts/partials/topmenu.blade.php @@ -38,7 +38,7 @@
-
+
@@ -139,7 +139,7 @@