Added rendering attribute hints
This commit is contained in:
parent
35596ec867
commit
c0c9a5576e
@ -4,6 +4,8 @@ namespace App\Classes\LDAP;
|
|||||||
|
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
|
use App\Classes\LDAP\Schema\AttributeType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents an attribute of an LDAP Object
|
* Represents an attribute of an LDAP Object
|
||||||
*/
|
*/
|
||||||
@ -12,6 +14,8 @@ class Attribute
|
|||||||
// Attribute Name
|
// Attribute Name
|
||||||
protected string $name;
|
protected string $name;
|
||||||
|
|
||||||
|
protected ?AttributeType $schema;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
# Source of this attribute definition
|
# Source of this attribute definition
|
||||||
protected $source;
|
protected $source;
|
||||||
@ -21,10 +25,15 @@ class Attribute
|
|||||||
protected Collection $values;
|
protected Collection $values;
|
||||||
|
|
||||||
// Can this attribute be deleted
|
// Can this attribute be deleted
|
||||||
protected bool $deletable = FALSE;
|
protected bool $is_deletable = FALSE;
|
||||||
|
|
||||||
// Is this attribute an internal attribute
|
// Is this attribute an internal attribute
|
||||||
protected bool $internal;
|
protected bool $is_internal;
|
||||||
|
|
||||||
|
// Is this attribute the RDN?
|
||||||
|
protected bool $is_rdn = FALSE;
|
||||||
|
|
||||||
|
protected Collection $required_by;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
protected $oldvalues = array();
|
protected $oldvalues = array();
|
||||||
@ -74,7 +83,6 @@ class Attribute
|
|||||||
public $page = 1;
|
public $page = 1;
|
||||||
public $order = 255;
|
public $order = 255;
|
||||||
public $ordersort = 255;
|
public $ordersort = 255;
|
||||||
public $rdn = false;
|
|
||||||
|
|
||||||
# Schema Aliases for this attribute (stored in lowercase)
|
# Schema Aliases for this attribute (stored in lowercase)
|
||||||
protected $aliases = array();
|
protected $aliases = array();
|
||||||
@ -89,6 +97,8 @@ class Attribute
|
|||||||
$this->name = $name;
|
$this->name = $name;
|
||||||
$this->values = collect($values);
|
$this->values = collect($values);
|
||||||
|
|
||||||
|
$this->schema = config('server')->schema('attributetypes',$name);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
# Should this attribute be hidden
|
# Should this attribute be hidden
|
||||||
if ($server->isAttrHidden($this->name))
|
if ($server->isAttrHidden($this->name))
|
||||||
@ -106,16 +116,24 @@ class Attribute
|
|||||||
|
|
||||||
public function __get(string $key): mixed
|
public function __get(string $key): mixed
|
||||||
{
|
{
|
||||||
switch ($key) {
|
return match ($key) {
|
||||||
case 'name':
|
// Can this attribute have more values
|
||||||
return $this->{$key};
|
'can_addvalues' => FALSE, // @todo
|
||||||
|
// Schema attribute description
|
||||||
|
'description' => $this->schema ? $this->schema->{$key} : NULL,
|
||||||
|
// Attribute hints
|
||||||
|
'hints' => $this->hints(),
|
||||||
|
// Is this an internal attribute
|
||||||
|
'is_internal' => isset($this->{$key}) && $this->{$key},
|
||||||
|
// We prefer the name as per the schema if it exists
|
||||||
|
'name' => $this->schema ? $this->schema->{$key} : $this->{$key},
|
||||||
|
// Attribute name in lower case
|
||||||
|
'name_lc' => strtolower($this->name),
|
||||||
|
// Is this attribute the RDN
|
||||||
|
'rdn' => $this->is_rdn,
|
||||||
|
|
||||||
case 'internal': return isset($this->{$key}) && $this->{$key};
|
default => throw new \Exception('Unknown key:' . $key),
|
||||||
case 'name_lc': return strtolower($this->name);
|
};
|
||||||
|
|
||||||
default:
|
|
||||||
throw new \Exception('Unknown key:'.$key);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -128,6 +146,64 @@ class Attribute
|
|||||||
return $this->values->join('<br>');
|
return $this->values->join('<br>');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return an instance of this attribute that is deletable.
|
||||||
|
* This is primarily used for rendering to know if to render delete options.
|
||||||
|
*
|
||||||
|
* @return Attribute
|
||||||
|
*/
|
||||||
|
public function deletable(): self
|
||||||
|
{
|
||||||
|
$clone = clone $this;
|
||||||
|
|
||||||
|
if (! $this->required_by->count())
|
||||||
|
$clone->is_deletable = TRUE;
|
||||||
|
|
||||||
|
return $clone;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the hints about this attribute, ie: RDN, Required, etc
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function hints(): array
|
||||||
|
{
|
||||||
|
$result = collect();
|
||||||
|
|
||||||
|
// Is this Attribute an RDN
|
||||||
|
if ($this->is_rdn)
|
||||||
|
$result->put(__('rdn'),__('This attribute is required for the RDN'));
|
||||||
|
|
||||||
|
// If this attribute name is an alias for the schema attribute name
|
||||||
|
// @todo
|
||||||
|
|
||||||
|
// objectClasses requiring this attribute
|
||||||
|
// eg: $result->put('required','Required by objectClasses: a,b');
|
||||||
|
if ($this->required_by->count())
|
||||||
|
$result->put(__('required'),sprintf('%s: %s',__('Required Attribute by ObjectClass(es)'),$this->required_by->join(',')));
|
||||||
|
|
||||||
|
return $result->toArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setRDN(): void
|
||||||
|
{
|
||||||
|
$this->is_rdn = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the name of the attribute.
|
* Return the name of the attribute.
|
||||||
*
|
*
|
||||||
@ -354,20 +430,6 @@ class Attribute
|
|||||||
$this->justModified();
|
$this->justModified();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isInternal() {
|
|
||||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
|
||||||
debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->internal);
|
|
||||||
|
|
||||||
return $this->internal;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setInternal() {
|
|
||||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
|
||||||
debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs);
|
|
||||||
|
|
||||||
$this->internal = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function isRequired() {
|
public function isRequired() {
|
||||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
||||||
debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs);
|
debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs);
|
||||||
@ -644,25 +706,6 @@ class Attribute
|
|||||||
return $this->verify;
|
return $this->verify;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setRDN($rdn) {
|
|
||||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
|
||||||
debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs);
|
|
||||||
|
|
||||||
$this->rdn = $rdn;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return if this attribute is an RDN attribute
|
|
||||||
*
|
|
||||||
* @return boolean
|
|
||||||
*
|
|
||||||
public function isRDN() {
|
|
||||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
|
||||||
debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs,$this->rdn);
|
|
||||||
|
|
||||||
return $this->rdn;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Capture all the LDAP details we are interested in
|
* Capture all the LDAP details we are interested in
|
||||||
*
|
*
|
||||||
@ -921,18 +964,4 @@ class Attribute
|
|||||||
debug_dump_backtrace(sprintf('Unknown JS request %s',$type),1);
|
debug_dump_backtrace(sprintf('Unknown JS request %s',$type),1);
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
|
||||||
* Return an instance of this attribute that is deletable.
|
|
||||||
* This is primarily used for rendering to know if to render delete options.
|
|
||||||
*
|
|
||||||
* @return Attribute
|
|
||||||
*/
|
|
||||||
public function deletable(): self
|
|
||||||
{
|
|
||||||
$clone = clone $this;
|
|
||||||
$clone->deletable = TRUE;
|
|
||||||
|
|
||||||
return $clone;
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -30,7 +30,7 @@ final class JpegPhoto extends Binary
|
|||||||
$result .= sprintf('<td><img class="jpegphoto" src="data:%s;base64, %s" />%s</td>',
|
$result .= sprintf('<td><img class="jpegphoto" src="data:%s;base64, %s" />%s</td>',
|
||||||
$x,
|
$x,
|
||||||
base64_encode($value),
|
base64_encode($value),
|
||||||
$this->deletable ? sprintf('<br><span class="btn btn-sm btn-danger"><i class="fas fa-trash-alt"></i> %s</span>',__('Delete')) : '');
|
$this->is_deletable ? sprintf('<br><span class="btn btn-sm btn-danger"><i class="fas fa-trash-alt"></i> %s</span>',__('Delete')) : '');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,5 +9,5 @@ use App\Classes\LDAP\Attribute;
|
|||||||
*/
|
*/
|
||||||
abstract class Internal extends Attribute
|
abstract class Internal extends Attribute
|
||||||
{
|
{
|
||||||
protected bool $internal = TRUE;
|
protected bool $is_internal = TRUE;
|
||||||
}
|
}
|
@ -262,6 +262,7 @@ class AttributeType extends Base {
|
|||||||
case 'equality': return $this->equality;
|
case 'equality': return $this->equality;
|
||||||
case 'max_length': return $this->max_length;
|
case 'max_length': return $this->max_length;
|
||||||
case 'ordering': return $this->ordering;
|
case 'ordering': return $this->ordering;
|
||||||
|
case 'required_by_object_classes': return $this->required_by_object_classes;
|
||||||
case 'sub_str_rule': return $this->sub_str_rule;
|
case 'sub_str_rule': return $this->sub_str_rule;
|
||||||
case 'sup_attribute': return $this->sup_attribute;
|
case 'sup_attribute': return $this->sup_attribute;
|
||||||
case 'syntax': return $this->syntax;
|
case 'syntax': return $this->syntax;
|
||||||
@ -528,6 +529,17 @@ class AttributeType extends Base {
|
|||||||
$this->aliases->forget($x);
|
$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.
|
* Sets this attribute's list of aliases.
|
||||||
*
|
*
|
||||||
|
@ -17,7 +17,16 @@ class Entry extends Model
|
|||||||
$result = collect();
|
$result = collect();
|
||||||
|
|
||||||
foreach (parent::getAttributes() as $attribute => $value) {
|
foreach (parent::getAttributes() as $attribute => $value) {
|
||||||
$result->put($attribute,Factory::create($attribute,$value));
|
$o = Factory::create($attribute,$value);
|
||||||
|
|
||||||
|
// Set the rdn flag
|
||||||
|
if (preg_match('/^'.$attribute.'=/i',$this->dn))
|
||||||
|
$o->setRDN();
|
||||||
|
|
||||||
|
// Set required flag
|
||||||
|
$o->required_by(collect($this->getAttribute('objectclass')));
|
||||||
|
|
||||||
|
$result->put($attribute,$o);
|
||||||
}
|
}
|
||||||
|
|
||||||
$sort = collect(config('ldap.attr_display_order',[]))->transform(function($item) { return strtolower($item); });
|
$sort = collect(config('ldap.attr_display_order',[]))->transform(function($item) { return strtolower($item); });
|
||||||
@ -67,7 +76,7 @@ class Entry extends Model
|
|||||||
public function getVisibleAttributes(): Collection
|
public function getVisibleAttributes(): Collection
|
||||||
{
|
{
|
||||||
return collect($this->getAttributes())->filter(function($item) {
|
return collect($this->getAttributes())->filter(function($item) {
|
||||||
return ! $item->internal;
|
return ! $item->is_internal;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -430,49 +430,6 @@ class PageRender extends Visitor {
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
#@todo this function shouldnt re-calculate requiredness, it should be known in the template already - need to set the ldaptype when initiating the attribute.
|
|
||||||
protected function getNoteRequiredAttribute($attribute) {
|
|
||||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
|
||||||
debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs);
|
|
||||||
|
|
||||||
if (DEBUGTMP) printf('<font size=-2>%s</font><br />',__METHOD__);
|
|
||||||
|
|
||||||
$required_by = '';
|
|
||||||
$sattr_required = '';
|
|
||||||
|
|
||||||
# Is this attribute required by an objectClass ?
|
|
||||||
$sattr = $this->getServer()->getSchemaAttribute($attribute->getName());
|
|
||||||
if ($sattr)
|
|
||||||
$sattr_required = $sattr->getRequiredByObjectClasses();
|
|
||||||
|
|
||||||
if ($sattr_required) {
|
|
||||||
$oc = $this->template->getAttribute('objectclass');
|
|
||||||
|
|
||||||
if ($oc)
|
|
||||||
foreach ($oc->getValues() as $objectclass) {
|
|
||||||
# If this objectclass is in our required list
|
|
||||||
if (in_array_ignore_case($objectclass,$sattr_required)) {
|
|
||||||
$required_by .= sprintf('%s ',$objectclass);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
# If not, see if it is in our parent.
|
|
||||||
$sattr = $this->getServer()->getSchemaObjectClass($objectclass);
|
|
||||||
|
|
||||||
if (array_intersect($sattr->getParents(),$sattr_required))
|
|
||||||
$required_by .= sprintf('%s ',$objectclass);
|
|
||||||
}
|
|
||||||
|
|
||||||
else
|
|
||||||
debug_dump_backtrace('How can there be no objectclasses?',1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($required_by)
|
|
||||||
return sprintf('<acronym title="%s %s">%s</acronym>',_('Required attribute for objectClass(es)'),$required_by,_('required'));
|
|
||||||
else
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function getNoteRDNAttribute($attribute) {
|
protected function getNoteRDNAttribute($attribute) {
|
||||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
||||||
debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs);
|
debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs);
|
||||||
|
@ -1766,34 +1766,6 @@ function random_salt($length) {
|
|||||||
return $str;
|
return $str;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Given a DN string, this returns the 'RDN' portion of the string.
|
|
||||||
* For example. given 'cn=Manager,dc=example,dc=com', this function returns
|
|
||||||
* 'cn=Manager' (it is really the exact opposite of ds_ldap::getContainer()).
|
|
||||||
*
|
|
||||||
* @param string The DN whose RDN to return.
|
|
||||||
* @param boolean If true, include attributes in the RDN string. See http://php.net/ldap_explode_dn for details
|
|
||||||
* @return string The RDN
|
|
||||||
*/
|
|
||||||
function get_rdn($dn,$include_attrs=0,$decode=false) {
|
|
||||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
|
||||||
debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs);
|
|
||||||
|
|
||||||
if (is_null($dn))
|
|
||||||
return null;
|
|
||||||
|
|
||||||
$rdn = pla_explode_dn($dn,$include_attrs);
|
|
||||||
if (! count($rdn) || ! isset($rdn[0]))
|
|
||||||
return $dn;
|
|
||||||
|
|
||||||
if ($decode)
|
|
||||||
$rdn = dn_unescape($rdn[0]);
|
|
||||||
else
|
|
||||||
$rdn = $rdn[0];
|
|
||||||
|
|
||||||
return $rdn;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Split an RDN into its attributes
|
* Split an RDN into its attributes
|
||||||
*/
|
*/
|
||||||
|
@ -28,17 +28,24 @@
|
|||||||
<table class="table">
|
<table class="table">
|
||||||
@foreach ($o->getVisibleAttributes() as $ao)
|
@foreach ($o->getVisibleAttributes() as $ao)
|
||||||
<tr class="bg-light text-dark small">
|
<tr class="bg-light text-dark small">
|
||||||
<th class="w-25" colspan="2">
|
<th class="w-25">
|
||||||
{{ $ao->name }}
|
<abbr title="{{ $ao->description }}">{{ $ao->name }}</abbr>
|
||||||
<!-- Attribute Hints -->
|
<!-- Attribute Hints -->
|
||||||
<span class="float-right"></span>
|
<span class="float-right">
|
||||||
|
@foreach($ao->hints as $name => $description)
|
||||||
|
@if ($loop->index),@endif
|
||||||
|
<abbr title="{{ $description }}">{{ $name }}</abbr>
|
||||||
|
@endforeach
|
||||||
|
</span>
|
||||||
</th>
|
</th>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="pl-5">
|
<td class="pl-5">
|
||||||
{!! $ao->deletable() !!}<br>
|
{!! $ao->deletable() !!}<br>
|
||||||
|
@if ($ao->can_addvalues)
|
||||||
<span class="p-0 m-0" id="add{{ $ao->name_lc }}"></span>
|
<span class="p-0 m-0" id="add{{ $ao->name_lc }}"></span>
|
||||||
<span class="btn btn-sm btn-outline-primary mt-3 mb-3"><i class="fas fa-plus"></i> {{ __('Add Value') }}</span>
|
<span class="btn btn-sm btn-outline-primary mt-3 mb-3"><i class="fas fa-plus"></i> {{ __('Add Value') }}</span>
|
||||||
|
@endif
|
||||||
</td>
|
</td>
|
||||||
{{--
|
{{--
|
||||||
<td>@dump($ao)</td>
|
<td>@dump($ao)</td>
|
||||||
|
Loading…
Reference in New Issue
Block a user