diff --git a/README.md b/README.md index 743342d..934fff7 100644 --- a/README.md +++ b/README.md @@ -35,8 +35,8 @@ The update to v2 is progressing well - here is a list of work to do and done: - [X] Validate password is correct - [ ] JpegPhoto Create/Delete - [X] JpegPhoto Display - - [ ] ObjectClass Add/Remove - - [ ] Add additional required attributes (for ObjectClass Addition) + - [X] ObjectClass Add/Remove + - [X] Add additional required attributes (for ObjectClass Addition) - [ ] Remove existing required attributes (for ObjectClass Removal) - [X] Add additional values to Attributes that support multiple values - [X] Delete extra values for Attributes that support multiple values diff --git a/app/Classes/LDAP/Attribute.php b/app/Classes/LDAP/Attribute.php index 8db210b..fc15cb4 100644 --- a/app/Classes/LDAP/Attribute.php +++ b/app/Classes/LDAP/Attribute.php @@ -33,9 +33,6 @@ class Attribute implements \Countable, \ArrayAccess, \Iterator // Is this attribute the RDN? protected bool $is_rdn = FALSE; - // Objectclasses that require this attribute - protected Collection $required_by; - // MIN/MAX number of values protected int $min_values_count = 0; protected int $max_values_count = 0; @@ -102,7 +99,6 @@ class Attribute implements \Countable, \ArrayAccess, \Iterator $this->name = $name; $this->values = collect($values); $this->lang_tags = collect(); - $this->required_by = collect(); $this->oldValues = collect($values); // No need to load our schema for internal attributes @@ -149,6 +145,10 @@ class Attribute implements \Countable, \ArrayAccess, \Iterator 'old_values' => $this->oldValues, // Attribute values 'values' => $this->values, + // Required by Object Classes + 'required_by' => $this->schema->required_by_object_classes, + // Used in Object Classes + 'used_in' => $this->schema->used_in_object_classes, default => throw new \Exception('Unknown key:' . $key), }; @@ -296,19 +296,6 @@ class Attribute implements \Countable, \ArrayAccess, \Iterator return Arr::get($this->values,$key); } - /** - * Set the objectclasses that require this attribute - * - * @param Collection $oc - * @return Collection - */ - public function required_by(Collection $oc): Collection - { - return $this->required_by = ($this->schema - ? $oc->intersect($this->schema->required_by_object_classes) - : collect()); - } - /** * If this attribute has RFC3866 Language Tags, this will enable those values to be captured * diff --git a/app/Classes/LDAP/Schema/AttributeType.php b/app/Classes/LDAP/Schema/AttributeType.php index b5482f5..c400056 100644 --- a/app/Classes/LDAP/Schema/AttributeType.php +++ b/app/Classes/LDAP/Schema/AttributeType.php @@ -549,17 +549,6 @@ final class AttributeType extends Base { $this->aliases->forget($x); } - /** - * Given a list of object classes, determine if this is a required attribute - * - * @param Collection $oc List of objectclasses to compare. - * @return Collection - */ - public function required_by(Collection $oc): Collection - { - return $oc->diff($this->required_by_object_classes); - } - /** * Sets this attribute's list of aliases. * diff --git a/app/Http/Controllers/APIController.php b/app/Http/Controllers/APIController.php index 5e9f81a..f228302 100644 --- a/app/Http/Controllers/APIController.php +++ b/app/Http/Controllers/APIController.php @@ -82,4 +82,21 @@ class APIController extends Controller abort(404); } } -} + + /** + * Return the required and additional attributes for an object class + * + * @param Request $request + * @param string $objectclass + * @return array + */ + public function schema_objectclass_attrs(Request $request,string $objectclass): array + { + $oc = config('server')->schema('objectclasses',$objectclass); + + return [ + 'must' => $oc->getMustAttrs()->pluck('name'), + 'may' => $oc->getMayAttrs()->pluck('name'), + ]; + } +} \ No newline at end of file diff --git a/app/Http/Controllers/HomeController.php b/app/Http/Controllers/HomeController.php index b2a698a..c71b829 100644 --- a/app/Http/Controllers/HomeController.php +++ b/app/Http/Controllers/HomeController.php @@ -85,7 +85,7 @@ class HomeController extends Controller ->with('o',new Attribute($id,[])) ->with('value',$request->value) ->with('loop',$xx) - : (new AttributeType(new Attribute($id,[]),TRUE))->render(); + : (new AttributeType(new Attribute($id,[]),TRUE,collect($request->oc ?: [])))->render(); return $x; } diff --git a/app/Ldap/Entry.php b/app/Ldap/Entry.php index abda927..06e3194 100644 --- a/app/Ldap/Entry.php +++ b/app/Ldap/Entry.php @@ -186,12 +186,8 @@ class Entry extends Model if (preg_match('/^'.$attribute.'=/i',$this->dn)) $o->setRDN(); - // Set required flag - $o->required_by(collect($this->getAttribute('objectclass'))); - // Store our original value to know if this attribute has changed - if ($x=Arr::get($this->original,$attribute)) - $o->oldValues($x); + $o->oldValues(Arr::get($this->original,$attribute,[])); $result->put($attribute,$o); } diff --git a/app/View/Components/AttributeType.php b/app/View/Components/AttributeType.php index 5608e12..eceeeb8 100644 --- a/app/View/Components/AttributeType.php +++ b/app/View/Components/AttributeType.php @@ -4,21 +4,24 @@ namespace App\View\Components; use Closure; use Illuminate\Contracts\View\View; +use Illuminate\Support\Collection; use Illuminate\View\Component; use App\Classes\LDAP\Attribute as LDAPAttribute; class AttributeType extends Component { + public Collection $oc; public LDAPAttribute $o; public bool $new; /** * Create a new component instance. */ - public function __construct(LDAPAttribute $o,bool $new=FALSE) + public function __construct(LDAPAttribute $o,bool $new=FALSE,Collection $oc=NULL) { $this->o = $o; + $this->oc = $oc; $this->new = $new; } @@ -29,6 +32,7 @@ class AttributeType extends Component { return view('components.attribute-type') ->with('o',$this->o) + ->with('oc',$this->oc) ->with('new',$this->new); } } \ No newline at end of file diff --git a/public/css/fixes.css b/public/css/fixes.css index 81d724e..fb6c723 100644 --- a/public/css/fixes.css +++ b/public/css/fixes.css @@ -295,4 +295,12 @@ select2-container--bootstrap-5 .select2-selection--multiple .select2-selection__ .select2-container--bootstrap-5 .select2-dropdown .select2-results__options .select2-results__option[role=group] .select2-results__group { color: #212529; font-weight: 800; +} + +div#objectclass .input-group-delete { + position: relative; + float: inline-end; + bottom: 30px; + right: 10px; + height: 5px; } \ No newline at end of file diff --git a/resources/views/components/attribute-type.blade.php b/resources/views/components/attribute-type.blade.php index 7484a44..23fde0f 100644 --- a/resources/views/components/attribute-type.blade.php +++ b/resources/views/components/attribute-type.blade.php @@ -4,7 +4,7 @@
- {{ $o->name }} + {{ $o->name }} @foreach($o->hints as $name => $description) diff --git a/resources/views/components/attribute/widget/objectclass.blade.php b/resources/views/components/attribute/widget/objectclass.blade.php index 932aec4..3a8d318 100644 --- a/resources/views/components/attribute/widget/objectclass.blade.php +++ b/resources/views/components/attribute/widget/objectclass.blade.php @@ -1,19 +1,12 @@ -
- - ($e=$errors->get($o->name_lc.'.'.$loop->index)),'mb-1','border-focus'=>$o->values->contains($value)]) name="{{ $o->name_lc }}[]" value="{{ $value }}" placeholder="{{ Arr::get($o->values,$loop->index,'['.__('NEW').']') }}" @readonly(true)> -
- @if($e) - {{ join('|',$e) }} - @endif + +
+ + ($e=$errors->get($o->name_lc.'.'.$loop->index)),'mb-1','border-focus'=>$o->values->contains($value)]) name="{{ $o->name_lc }}[]" value="{{ $value }}" placeholder="{{ Arr::get($o->values,$loop->index,'['.__('NEW').']') }}" @readonly(true)> +
+ @if($e) + {{ join('|',$e) }} + @endif +
-
- - - \ No newline at end of file + + \ No newline at end of file diff --git a/resources/views/components/attribute/widget/options.blade.php b/resources/views/components/attribute/widget/options.blade.php index 6b1649e..cafc189 100644 --- a/resources/views/components/attribute/widget/options.blade.php +++ b/resources/views/components/attribute/widget/options.blade.php @@ -68,42 +68,97 @@ var newadded = $('select#newoc').val(); // If nothing selected, we dont have anything to do - if (! newadded.length) + if (added_oc.sort().join('|') == newadded.sort().join('|')) return; + var attrs = $('[data-attr-name]').map(function() { + return $(this).data('attrName'); + }); + // Find out what was selected, and add them newadded.forEach(function (item) { if (added_oc.indexOf(item) !== -1) return; + // Add attribute to the page $.ajax({ - type: 'GET', + type: 'POST', beforeSend: function() {}, success: function(data) { - console.log(data); $('#{{ $o->name_lc }}').append(data); - console.log('set to:'+item); }, error: function(e) { if (e.status != 412) alert('That didnt work? Please try again....'); }, url: '{{ url('entry/attr/add',[$o->name_lc]) }}', - data: {noheader: true,value: item,loop: c++}, // @todo can we omit loop and c + data: { + noheader: true, + value: item, + objectclasses: oc, + loop: c++, // @todo can we omit loop and c + }, + cache: false + }); + + $.ajax({ + type: 'POST', + beforeSend: function() {}, + success: function(data) { + // Render any must attributes + if (data.must.length) { + data.must.forEach(function(item) { + // Add attribute to the page + $.ajax({ + type: 'POST', + beforeSend: function() {}, + success: function(data) { + $('#newattrs').append(data); + }, + error: function(e) { + if (e.status != 412) + alert('That didnt work? Please try again....'); + }, + url: '{{ url('entry/attr/add') }}/'+item, + data: { + value: item, + objectclasses: oc, + loop: c++, // @todo can we omit loop and c + }, + cache: false + }); + }) + } + + // Add attributes to "Add new Attribute" that are now available + if (data.may.length) { + var newattr = $('select#newattr'); + + // @todo It might be nice to resort this options + data.may.forEach(function(item) { + newattr.append(new Option(item,item,false,false)); + }); + } + }, + error: function(e) { + if (e.status != 412) + alert('That didnt work? Please try again....'); + }, + url: '{{ url('api/schema/objectclass/attrs') }}/'+item, cache: false }); - // @todo add any required attributes that are defined required as a result of adding this OC - // @todo Add attributes to "Add new Attribute" that are now available }); // Loop through added_oc, and remove anything not in newadded added_oc.forEach(function(item) { if (newadded.indexOf(item) === -1) { - $('input[value="'+item+'"]').parent().empty(); + $('span#objectclass_'+item).empty(); // @todo remove any required attributes that are no longer defined as a result of removing this OC + console.log('Remove required attributes of:'+item); // @todo Remove attributes from "Add new Attribute" that are no longer available + console.log('Remove additional attributes of:'+item); } }); diff --git a/resources/views/frames/dn.blade.php b/resources/views/frames/dn.blade.php index a667ad5..7297660 100644 --- a/resources/views/frames/dn.blade.php +++ b/resources/views/frames/dn.blade.php @@ -31,7 +31,7 @@ @foreach ($o->getVisibleAttributes() as $ao) - + @endforeach
@@ -173,6 +173,7 @@ @section('page-scripts')