Compare commits
13 Commits
2b012b689c
...
df1641e945
Author | SHA1 | Date | |
---|---|---|---|
df1641e945 | |||
ac821750ef | |||
649749f9c1 | |||
5d3b8609bb | |||
93640959db | |||
f667250b2c | |||
4a84c25ac7 | |||
8ab5b4f35c | |||
de2d139288 | |||
d326d3c308 | |||
d3fc9c135f | |||
eb6e0b8d43 | |||
b01f7d5baf |
@ -1,6 +1,10 @@
|
|||||||
name: Create Docker Image
|
name: Create Docker Image
|
||||||
run-name: ${{ gitea.actor }} Building Docker Image 🐳
|
run-name: ${{ gitea.actor }} Building Docker Image 🐳
|
||||||
on: [push]
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- '*'
|
||||||
|
- '!master'
|
||||||
env:
|
env:
|
||||||
DOCKER_HOST: tcp://127.0.0.1:2375
|
DOCKER_HOST: tcp://127.0.0.1:2375
|
||||||
ASSETS: c2780a3
|
ASSETS: c2780a3
|
||||||
|
@ -17,31 +17,28 @@ class Attribute implements \Countable, \ArrayAccess, \Iterator
|
|||||||
protected string $name;
|
protected string $name;
|
||||||
private int $counter = 0;
|
private int $counter = 0;
|
||||||
|
|
||||||
protected ?AttributeType $schema = NULL;
|
|
||||||
|
|
||||||
/*
|
|
||||||
# Source of this attribute definition
|
|
||||||
protected $source;
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Current and Old Values
|
|
||||||
protected Collection $values;
|
|
||||||
|
|
||||||
// Is this attribute an internal attribute
|
// Is this attribute an internal attribute
|
||||||
protected bool $is_internal = FALSE;
|
protected(set) bool $is_internal = FALSE;
|
||||||
|
|
||||||
// Is this attribute the RDN?
|
|
||||||
protected bool $is_rdn = FALSE;
|
|
||||||
|
|
||||||
// MIN/MAX number of values
|
// MIN/MAX number of values
|
||||||
protected int $min_values_count = 0;
|
protected(set) int $min_values_count = 0;
|
||||||
protected int $max_values_count = 0;
|
protected(set) int $max_values_count = 0;
|
||||||
|
|
||||||
// RFC3866 Language Tags
|
// RFC3866 Language Tags
|
||||||
|
/* @deprecated use $values/$values_old when playing with language tags */
|
||||||
protected Collection $lang_tags;
|
protected Collection $lang_tags;
|
||||||
|
|
||||||
|
// The schema's representation of this attribute
|
||||||
|
protected(set) ?AttributeType $schema;
|
||||||
|
|
||||||
|
// 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
|
// The old values for this attribute - helps with isDirty() to determine if there is an update pending
|
||||||
protected Collection $oldValues;
|
protected(set) Collection $values_old;
|
||||||
|
// Current Values
|
||||||
|
public Collection $values;
|
||||||
|
// The objectclasses of the entry that has this attribute
|
||||||
|
protected(set) Collection $oc;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
# Has the attribute been modified
|
# Has the attribute been modified
|
||||||
@ -94,12 +91,23 @@ class Attribute implements \Countable, \ArrayAccess, \Iterator
|
|||||||
protected $postvalue = array();
|
protected $postvalue = array();
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public function __construct(string $name,array $values)
|
/**
|
||||||
|
* Create an 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
|
||||||
|
*/
|
||||||
|
public function __construct(string $dn,string $name,array $values,array $oc=[])
|
||||||
{
|
{
|
||||||
|
$this->dn = $dn;
|
||||||
$this->name = $name;
|
$this->name = $name;
|
||||||
$this->values = collect($values);
|
$this->values_old = collect($values);
|
||||||
|
|
||||||
|
$this->values = collect();
|
||||||
|
$this->oc = collect($oc);
|
||||||
$this->lang_tags = collect();
|
$this->lang_tags = collect();
|
||||||
$this->oldValues = collect($values);
|
|
||||||
|
|
||||||
$this->schema = (new Server)
|
$this->schema = (new Server)
|
||||||
->schema('attributetypes',$name);
|
->schema('attributetypes',$name);
|
||||||
@ -132,18 +140,14 @@ class Attribute implements \Countable, \ArrayAccess, \Iterator
|
|||||||
'hints' => $this->hints(),
|
'hints' => $this->hints(),
|
||||||
// Can this attribute be edited
|
// Can this attribute be edited
|
||||||
'is_editable' => $this->schema ? $this->schema->{$key} : NULL,
|
'is_editable' => $this->schema ? $this->schema->{$key} : NULL,
|
||||||
// Is this an internal attribute
|
// Objectclasses that required this attribute for an LDAP entry
|
||||||
'is_internal' => isset($this->{$key}) && $this->{$key},
|
'required' => $this->required(),
|
||||||
// Is this attribute the RDN
|
// Is this attribute an RDN attribute
|
||||||
'is_rdn' => $this->is_rdn,
|
'is_rdn' => $this->isRDN(),
|
||||||
// We prefer the name as per the schema if it exists
|
// We prefer the name as per the schema if it exists
|
||||||
'name' => $this->schema ? $this->schema->{$key} : $this->{$key},
|
'name' => $this->schema ? $this->schema->{$key} : $this->{$key},
|
||||||
// Attribute name in lower case
|
// Attribute name in lower case
|
||||||
'name_lc' => strtolower($this->name),
|
'name_lc' => strtolower($this->name),
|
||||||
// Old Values
|
|
||||||
'old_values' => $this->oldValues,
|
|
||||||
// Attribute values
|
|
||||||
'values' => $this->values,
|
|
||||||
// Required by Object Classes
|
// Required by Object Classes
|
||||||
'required_by' => $this->schema?->required_by_object_classes ?: collect(),
|
'required_by' => $this->schema?->required_by_object_classes ?: collect(),
|
||||||
// Used in Object Classes
|
// Used in Object Classes
|
||||||
@ -153,17 +157,6 @@ class Attribute implements \Countable, \ArrayAccess, \Iterator
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __set(string $key,mixed $values): void
|
|
||||||
{
|
|
||||||
switch ($key) {
|
|
||||||
case 'value':
|
|
||||||
$this->values = collect($values);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function __toString(): string
|
public function __toString(): string
|
||||||
{
|
{
|
||||||
return $this->name;
|
return $this->name;
|
||||||
@ -240,11 +233,8 @@ class Attribute implements \Countable, \ArrayAccess, \Iterator
|
|||||||
// If this attribute name is an alias for the schema attribute name
|
// If this attribute name is an alias for the schema attribute name
|
||||||
// @todo
|
// @todo
|
||||||
|
|
||||||
// objectClasses requiring this attribute
|
if ($this->required()->count())
|
||||||
// @todo limit this to this DNs objectclasses
|
$result->put(__('required'),sprintf('%s: %s',__('Required Attribute by ObjectClass(es)'),$this->required()->join(', ')));
|
||||||
// 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(',')));
|
|
||||||
|
|
||||||
// This attribute has language tags
|
// This attribute has language tags
|
||||||
if ($this->lang_tags->count())
|
if ($this->lang_tags->count())
|
||||||
@ -260,13 +250,24 @@ class Attribute implements \Countable, \ArrayAccess, \Iterator
|
|||||||
*/
|
*/
|
||||||
public function isDirty(): bool
|
public function isDirty(): bool
|
||||||
{
|
{
|
||||||
return ($this->oldValues->count() !== $this->values->count())
|
return ($this->values_old->count() !== $this->values->count())
|
||||||
|| ($this->values->diff($this->oldValues)->count() !== 0);
|
|| ($this->values->diff($this->values_old)->count() !== 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function oldValues(array $array): void
|
/**
|
||||||
|
* Work out if this attribute is an RDN attribute
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isRDN(): bool
|
||||||
{
|
{
|
||||||
$this->oldValues = collect($array);
|
// If we dont have an DN, then we cant know
|
||||||
|
if (! $this->dn)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
$rdns = collect(explode('+',substr($this->dn,0,strpos($this->dn,','))));
|
||||||
|
|
||||||
|
return $rdns->filter(fn($item) => str_starts_with($item,$this->name.'='))->count() > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -292,7 +293,7 @@ class Attribute implements \Countable, \ArrayAccess, \Iterator
|
|||||||
|
|
||||||
public function render_item_old(int $key): ?string
|
public function render_item_old(int $key): ?string
|
||||||
{
|
{
|
||||||
return Arr::get($this->old_values,$key);
|
return Arr::get($this->values_old,$key);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function render_item_new(int $key): ?string
|
public function render_item_new(int $key): ?string
|
||||||
@ -300,20 +301,29 @@ class Attribute implements \Countable, \ArrayAccess, \Iterator
|
|||||||
return Arr::get($this->values,$key);
|
return Arr::get($this->values,$key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Work out if this attribute is required by an objectClass the entry has
|
||||||
|
*
|
||||||
|
* @return Collection
|
||||||
|
*/
|
||||||
|
public function required(): Collection
|
||||||
|
{
|
||||||
|
// If we dont have any objectclasses then we cant know if it is required
|
||||||
|
return $this->oc->count()
|
||||||
|
? $this->oc->intersect($this->schema->required_by_object_classes->keys())->sort()
|
||||||
|
: collect();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If this attribute has RFC3866 Language Tags, this will enable those values to be captured
|
* If this attribute has RFC3866 Language Tags, this will enable those values to be captured
|
||||||
*
|
*
|
||||||
* @param string $tag
|
* @param string $tag
|
||||||
* @param array $value
|
* @param array $value
|
||||||
* @return void
|
* @return void
|
||||||
|
* @deprecated
|
||||||
*/
|
*/
|
||||||
public function setLangTag(string $tag,array $value): void
|
public function setLangTag(string $tag,array $value): void
|
||||||
{
|
{
|
||||||
$this->lang_tags->put($tag,$value);
|
$this->lang_tags->put($tag,$value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setRDN(): void
|
|
||||||
{
|
|
||||||
$this->is_rdn = TRUE;
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -7,6 +7,6 @@ use App\Classes\LDAP\Attribute;
|
|||||||
/**
|
/**
|
||||||
* Represents an attribute whose values are binary
|
* Represents an attribute whose values are binary
|
||||||
*/
|
*/
|
||||||
class Binary extends Attribute
|
abstract class Binary extends Attribute
|
||||||
{
|
{
|
||||||
}
|
}
|
@ -49,15 +49,17 @@ class Factory
|
|||||||
/**
|
/**
|
||||||
* Create the new Object for an attribute
|
* Create the new Object for an attribute
|
||||||
*
|
*
|
||||||
|
* @param string $dn
|
||||||
* @param string $attribute
|
* @param string $attribute
|
||||||
* @param array $values
|
* @param array $values
|
||||||
|
* @param array $oc
|
||||||
* @return Attribute
|
* @return Attribute
|
||||||
*/
|
*/
|
||||||
public static function create(string $attribute,array $values): Attribute
|
public static function create(string $dn,string $attribute,array $values,array $oc=[]): Attribute
|
||||||
{
|
{
|
||||||
$class = Arr::get(self::map,strtolower($attribute),Attribute::class);
|
$class = Arr::get(self::map,strtolower($attribute),Attribute::class);
|
||||||
Log::debug(sprintf('%s:Creating LDAP Attribute [%s] as [%s]',static::LOGKEY,$attribute,$class));
|
Log::debug(sprintf('%s:Creating LDAP Attribute [%s] as [%s]',static::LOGKEY,$attribute,$class));
|
||||||
|
|
||||||
return new $class($attribute,$values);
|
return new $class($dn,$attribute,$values,$oc);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -11,7 +11,7 @@ use App\Classes\LDAP\Attribute;
|
|||||||
*/
|
*/
|
||||||
abstract class Internal extends Attribute
|
abstract class Internal extends Attribute
|
||||||
{
|
{
|
||||||
protected bool $is_internal = TRUE;
|
protected(set) bool $is_internal = TRUE;
|
||||||
|
|
||||||
public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE): View
|
public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE): View
|
||||||
{
|
{
|
||||||
|
@ -26,7 +26,7 @@ final class KrbPrincipalKey extends Attribute
|
|||||||
|
|
||||||
public function render_item_old(int $key): ?string
|
public function render_item_old(int $key): ?string
|
||||||
{
|
{
|
||||||
$pw = Arr::get($this->oldValues,$key);
|
$pw = Arr::get($this->values_old,$key);
|
||||||
return $pw
|
return $pw
|
||||||
? str_repeat('*',16)
|
? str_repeat('*',16)
|
||||||
: NULL;
|
: NULL;
|
||||||
|
@ -11,7 +11,7 @@ use Illuminate\Support\Collection;
|
|||||||
* Represents an attribute whose value is a Kerberos Ticket Flag
|
* Represents an attribute whose value is a Kerberos Ticket Flag
|
||||||
* See RFC4120
|
* See RFC4120
|
||||||
*/
|
*/
|
||||||
class KrbTicketFlags extends Attribute
|
final class KrbTicketFlags extends Attribute
|
||||||
{
|
{
|
||||||
private const DISALLOW_POSTDATED = 0x00000001;
|
private const DISALLOW_POSTDATED = 0x00000001;
|
||||||
private const DISALLOW_FORWARDABLE = 0x00000002;
|
private const DISALLOW_FORWARDABLE = 0x00000002;
|
||||||
|
@ -15,13 +15,21 @@ final class ObjectClass extends Attribute
|
|||||||
// The schema ObjectClasses for this objectclass of a DN
|
// The schema ObjectClasses for this objectclass of a DN
|
||||||
protected Collection $oc_schema;
|
protected Collection $oc_schema;
|
||||||
|
|
||||||
public function __construct(string $name,array $values)
|
/**
|
||||||
|
* Create an ObjectClass 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
|
||||||
|
*/
|
||||||
|
public function __construct(string $dn,string $name,array $values,array $oc=[])
|
||||||
{
|
{
|
||||||
parent::__construct($name,$values);
|
parent::__construct($dn,$name,$values,['top']);
|
||||||
|
|
||||||
$this->oc_schema = config('server')
|
$this->oc_schema = config('server')
|
||||||
->schema('objectclasses')
|
->schema('objectclasses')
|
||||||
->filter(fn($item)=>$this->values->contains($item->name));
|
->filter(fn($item)=>$this->values->merge($this->values_old)->unique()->contains($item->name));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __get(string $key): mixed
|
public function __get(string $key): mixed
|
||||||
|
@ -87,7 +87,7 @@ final class Password extends Attribute
|
|||||||
|
|
||||||
public function render_item_old(int $key): ?string
|
public function render_item_old(int $key): ?string
|
||||||
{
|
{
|
||||||
$pw = Arr::get($this->oldValues,$key);
|
$pw = Arr::get($this->values_old,$key);
|
||||||
return $pw
|
return $pw
|
||||||
? (((($x=$this->hash($pw)) && ($x::id() !== '*clear*')) ? sprintf('{%s}',$x::shortid()) : '').str_repeat('*',16))
|
? (((($x=$this->hash($pw)) && ($x::id() !== '*clear*')) ? sprintf('{%s}',$x::shortid()) : '').str_repeat('*',16))
|
||||||
: NULL;
|
: NULL;
|
||||||
|
@ -12,7 +12,7 @@ final class SMD5 extends Base
|
|||||||
return $source === $this->encode($compare,$this->salted_salt($source));
|
return $source === $this->encode($compare,$this->salted_salt($source));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function encode(string $password,string $salt=NULL): string
|
public function encode(string $password,?string $salt=NULL): string
|
||||||
{
|
{
|
||||||
if (is_null($salt))
|
if (is_null($salt))
|
||||||
$salt = hex2bin(random_salt(self::salt));
|
$salt = hex2bin(random_salt(self::salt));
|
||||||
|
@ -12,7 +12,7 @@ final class SSHA extends Base
|
|||||||
return $source === $this->encode($compare,$this->salted_salt($source));
|
return $source === $this->encode($compare,$this->salted_salt($source));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function encode(string $password,string $salt=NULL): string
|
public function encode(string $password,?string $salt=NULL): string
|
||||||
{
|
{
|
||||||
return sprintf('{%s}%s',self::key,$this->salted_hash($password,'sha1',self::salt,$salt));
|
return sprintf('{%s}%s',self::key,$this->salted_hash($password,'sha1',self::salt,$salt));
|
||||||
}
|
}
|
||||||
|
@ -3,9 +3,9 @@
|
|||||||
namespace App\Classes\LDAP;
|
namespace App\Classes\LDAP;
|
||||||
|
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
|
use LdapRecord\LdapRecordException;
|
||||||
|
|
||||||
use App\Exceptions\Import\GeneralException;
|
use App\Exceptions\Import\GeneralException;
|
||||||
use App\Exceptions\Import\ObjectExistsException;
|
|
||||||
use App\Ldap\Entry;
|
use App\Ldap\Entry;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -48,7 +48,6 @@ abstract class Import
|
|||||||
* @param int $action
|
* @param int $action
|
||||||
* @return Collection
|
* @return Collection
|
||||||
* @throws GeneralException
|
* @throws GeneralException
|
||||||
* @throws ObjectExistsException
|
|
||||||
*/
|
*/
|
||||||
final protected function commit(Entry $o,int $action): Collection
|
final protected function commit(Entry $o,int $action): Collection
|
||||||
{
|
{
|
||||||
@ -57,15 +56,24 @@ abstract class Import
|
|||||||
try {
|
try {
|
||||||
$o->save();
|
$o->save();
|
||||||
|
|
||||||
} catch (\Exception $e) {
|
} catch (LdapRecordException $e) {
|
||||||
return collect([
|
if ($e->getDetailedError())
|
||||||
'dn'=>$o->getDN(),
|
return collect([
|
||||||
'result'=>sprintf('%d: %s (%s)',
|
'dn'=>$o->getDN(),
|
||||||
($x=$e->getDetailedError())->getErrorCode(),
|
'result'=>sprintf('%d: %s (%s)',
|
||||||
$x->getErrorMessage(),
|
($x=$e->getDetailedError())->getErrorCode(),
|
||||||
$x->getDiagnosticMessage(),
|
$x->getErrorMessage(),
|
||||||
)
|
$x->getDiagnosticMessage(),
|
||||||
]);
|
)
|
||||||
|
]);
|
||||||
|
else
|
||||||
|
return collect([
|
||||||
|
'dn'=>$o->getDN(),
|
||||||
|
'result'=>sprintf('%d: %s',
|
||||||
|
$e->getCode(),
|
||||||
|
$e->getMessage(),
|
||||||
|
)
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return collect(['dn'=>$o->getDN(),'result'=>__('Created')]);
|
return collect(['dn'=>$o->getDN(),'result'=>__('Created')]);
|
||||||
|
@ -46,7 +46,7 @@ class LDIF extends Import
|
|||||||
if (! $line) {
|
if (! $line) {
|
||||||
if (! is_null($o)) {
|
if (! is_null($o)) {
|
||||||
// Add the last attribute;
|
// Add the last attribute;
|
||||||
$o->addAttribute($attribute,$base64encoded ? base64_decode($value) : $value);
|
$o->addAttributeItem($attribute,$base64encoded ? base64_decode($value) : $value);
|
||||||
|
|
||||||
Log::debug(sprintf('%s: Committing Entry [%s]',self::LOGKEY,$o->getDN()));
|
Log::debug(sprintf('%s: Committing Entry [%s]',self::LOGKEY,$o->getDN()));
|
||||||
|
|
||||||
@ -125,7 +125,7 @@ class LDIF extends Import
|
|||||||
Log::debug(sprintf('%s: Adding Attribute [%s] value [%s] (%d)',self::LOGKEY,$attribute,$value,$c));
|
Log::debug(sprintf('%s: Adding Attribute [%s] value [%s] (%d)',self::LOGKEY,$attribute,$value,$c));
|
||||||
|
|
||||||
if ($value)
|
if ($value)
|
||||||
$o->addAttribute($attribute,$base64encoded ? base64_decode($value) : $value);
|
$o->addAttributeItem($attribute,$base64encoded ? base64_decode($value) : $value);
|
||||||
else
|
else
|
||||||
throw new GeneralException(sprintf('Attribute has no value [%s] (line %d)',$attribute,$c));
|
throw new GeneralException(sprintf('Attribute has no value [%s] (line %d)',$attribute,$c));
|
||||||
}
|
}
|
||||||
@ -147,7 +147,7 @@ class LDIF extends Import
|
|||||||
// We may still have a pending action
|
// We may still have a pending action
|
||||||
if ($action) {
|
if ($action) {
|
||||||
// Add the last attribute;
|
// Add the last attribute;
|
||||||
$o->addAttribute($attribute,$base64encoded ? base64_decode($value) : $value);
|
$o->addAttributeItem($attribute,$base64encoded ? base64_decode($value) : $value);
|
||||||
|
|
||||||
Log::debug(sprintf('%s: Committing Entry [%s]',self::LOGKEY,$o->getDN()));
|
Log::debug(sprintf('%s: Committing Entry [%s]',self::LOGKEY,$o->getDN()));
|
||||||
|
|
||||||
|
@ -320,11 +320,12 @@ final class AttributeType extends Base {
|
|||||||
* that is the list of objectClasses which must have this attribute.
|
* that is the list of objectClasses which must have this attribute.
|
||||||
*
|
*
|
||||||
* @param string $name The name of the objectClass to add.
|
* @param string $name The name of the objectClass to add.
|
||||||
|
* @param bool $structural
|
||||||
*/
|
*/
|
||||||
public function addRequiredByObjectClass(string $name): void
|
public function addRequiredByObjectClass(string $name,bool $structural): void
|
||||||
{
|
{
|
||||||
if (! $this->required_by_object_classes->contains($name))
|
if (! $this->required_by_object_classes->has($name))
|
||||||
$this->required_by_object_classes->push($name);
|
$this->required_by_object_classes->put($name,$structural);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -332,6 +333,7 @@ final class AttributeType extends Base {
|
|||||||
* that is the list of objectClasses which provide this attribute.
|
* that is the list of objectClasses which provide this attribute.
|
||||||
*
|
*
|
||||||
* @param string $name The name of the objectClass to add.
|
* @param string $name The name of the objectClass to add.
|
||||||
|
* @param bool $structural
|
||||||
*/
|
*/
|
||||||
public function addUsedInObjectClass(string $name,bool $structural): void
|
public function addUsedInObjectClass(string $name,bool $structural): void
|
||||||
{
|
{
|
||||||
@ -544,7 +546,7 @@ final class AttributeType extends Base {
|
|||||||
*/
|
*/
|
||||||
public function validation(array $array): ?array
|
public function validation(array $array): ?array
|
||||||
{
|
{
|
||||||
// For each item in array, we need to get the OC heirachy
|
// For each item in array, we need to get the OC hierarchy
|
||||||
$heirachy = collect($array)
|
$heirachy = collect($array)
|
||||||
->filter()
|
->filter()
|
||||||
->map(fn($item)=>config('server')
|
->map(fn($item)=>config('server')
|
||||||
|
@ -428,7 +428,7 @@ final class Server
|
|||||||
// Add Required By.
|
// Add Required By.
|
||||||
foreach ($must_attrs as $attr_name)
|
foreach ($must_attrs as $attr_name)
|
||||||
if ($this->attributetypes->has(strtolower($attr_name)))
|
if ($this->attributetypes->has(strtolower($attr_name)))
|
||||||
$this->attributetypes[strtolower($attr_name)]->addRequiredByObjectClass($object_class->name);
|
$this->attributetypes[strtolower($attr_name)]->addRequiredByObjectClass($object_class->name,$object_class->isStructural());
|
||||||
|
|
||||||
// Force May
|
// Force May
|
||||||
foreach ($object_class->getForceMayAttrs() as $attr_name)
|
foreach ($object_class->getForceMayAttrs() as $attr_name)
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
namespace App\Http\Controllers;
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
use Illuminate\Contracts\View\View;
|
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Arr;
|
use Illuminate\Support\Arr;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
@ -42,24 +41,14 @@ class HomeController extends Controller
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Debug Page
|
|
||||||
*
|
|
||||||
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View
|
|
||||||
*/
|
|
||||||
public function debug()
|
|
||||||
{
|
|
||||||
return view('debug');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new object in the LDAP server
|
* Create a new object in the LDAP server
|
||||||
*
|
*
|
||||||
* @param EntryAddRequest $request
|
* @param EntryAddRequest $request
|
||||||
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View
|
* @return View
|
||||||
* @throws InvalidUsage
|
* @throws InvalidUsage
|
||||||
*/
|
*/
|
||||||
public function entry_add(EntryAddRequest $request)
|
public function entry_add(EntryAddRequest $request): \Illuminate\View\View
|
||||||
{
|
{
|
||||||
if (! old('step',$request->validated('step')))
|
if (! old('step',$request->validated('step')))
|
||||||
abort(404);
|
abort(404);
|
||||||
@ -72,7 +61,7 @@ class HomeController extends Controller
|
|||||||
$o->objectclass = $x;
|
$o->objectclass = $x;
|
||||||
|
|
||||||
foreach($o->getAvailableAttributes()->filter(fn($item)=>$item->required) as $ao)
|
foreach($o->getAvailableAttributes()->filter(fn($item)=>$item->required) as $ao)
|
||||||
$o->addAttribute($ao,'');
|
$o->{$ao->name} = '';
|
||||||
|
|
||||||
$o->setRDNBase($key['dn']);
|
$o->setRDNBase($key['dn']);
|
||||||
}
|
}
|
||||||
@ -92,24 +81,24 @@ class HomeController extends Controller
|
|||||||
*
|
*
|
||||||
* @param Request $request
|
* @param Request $request
|
||||||
* @param string $id
|
* @param string $id
|
||||||
* @return \Closure|\Illuminate\Contracts\View\View|string
|
* @return \Illuminate\View\View
|
||||||
*/
|
*/
|
||||||
public function entry_attr_add(Request $request,string $id): string
|
public function entry_attr_add(Request $request,string $id): \Illuminate\View\View
|
||||||
{
|
{
|
||||||
$xx = new \stdClass;
|
$xx = new \stdClass;
|
||||||
$xx->index = 0;
|
$xx->index = 0;
|
||||||
|
|
||||||
$x = $request->noheader
|
$dn = $request->dn ? Crypt::decrypt($request->dn) : '';
|
||||||
? (string)view(sprintf('components.attribute.widget.%s',$id))
|
|
||||||
->with('o',Factory::create($id,[]))
|
return $request->noheader
|
||||||
|
? view(sprintf('components.attribute.widget.%s',$id))
|
||||||
|
->with('o',Factory::create($dn,$id,[],$request->objectclasses))
|
||||||
->with('value',$request->value)
|
->with('value',$request->value)
|
||||||
->with('loop',$xx)
|
->with('loop',$xx)
|
||||||
: (new AttributeType(Factory::create($id,[]),TRUE,collect($request->oc ?: [])))->render();
|
: new AttributeType(Factory::create($dn,$id,[],$request->objectclasses),TRUE)->render();
|
||||||
|
|
||||||
return $x;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function entry_create(EntryAddRequest $request)
|
public function entry_create(EntryAddRequest $request): \Illuminate\Http\RedirectResponse
|
||||||
{
|
{
|
||||||
$key = $this->request_key($request,collect(old()));
|
$key = $this->request_key($request,collect(old()));
|
||||||
|
|
||||||
@ -139,24 +128,21 @@ class HomeController extends Controller
|
|||||||
|
|
||||||
// @todo when we create an entry, and it already exists, enable a redirect to it
|
// @todo when we create an entry, and it already exists, enable a redirect to it
|
||||||
} catch (LdapRecordException $e) {
|
} catch (LdapRecordException $e) {
|
||||||
$request->flash();
|
return Redirect::back()
|
||||||
|
->withInput()
|
||||||
switch ($x=$e->getDetailedError()->getErrorCode()) {
|
->withErrors(sprintf('%s: %s - %s: %s',
|
||||||
case 8:
|
__('LDAP Server Error Code'),
|
||||||
return Redirect::to('/')
|
$e->getDetailedError()->getErrorCode(),
|
||||||
->withInput()
|
__($e->getDetailedError()->getErrorMessage()),
|
||||||
->withErrors(sprintf('%s: %s (%s)',__('LDAP Server Error Code'),$x,__($e->getDetailedError()->getErrorMessage())));
|
$e->getDetailedError()->getDiagnosticMessage(),
|
||||||
|
));
|
||||||
default:
|
|
||||||
abort(599,$e->getDetailedError()->getErrorMessage());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Redirect::to('/')
|
return Redirect::to('/')
|
||||||
->withFragment($o->getDNSecure());
|
->withFragment($o->getDNSecure());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function entry_delete(Request $request)
|
public function entry_delete(Request $request): \Illuminate\Http\RedirectResponse
|
||||||
{
|
{
|
||||||
$dn = Crypt::decryptString($request->dn);
|
$dn = Crypt::decryptString($request->dn);
|
||||||
|
|
||||||
@ -196,7 +182,7 @@ class HomeController extends Controller
|
|||||||
->with('success',[sprintf('%s: %s',__('Deleted'),$dn)]);
|
->with('success',[sprintf('%s: %s',__('Deleted'),$dn)]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function entry_export(Request $request,string $id)
|
public function entry_export(Request $request,string $id): \Illuminate\View\View
|
||||||
{
|
{
|
||||||
$dn = Crypt::decryptString($id);
|
$dn = Crypt::decryptString($id);
|
||||||
|
|
||||||
@ -215,12 +201,13 @@ class HomeController extends Controller
|
|||||||
/**
|
/**
|
||||||
* Render an available list of objectclasses for an Entry
|
* Render an available list of objectclasses for an Entry
|
||||||
*
|
*
|
||||||
* @param string $id
|
* @param Request $request
|
||||||
* @return mixed
|
* @return Collection
|
||||||
*/
|
*/
|
||||||
public function entry_objectclass_add(Request $request)
|
public function entry_objectclass_add(Request $request): Collection
|
||||||
{
|
{
|
||||||
$oc = Factory::create('objectclass',$request->oc);
|
$dn = $request->key ? Crypt::decryptString($request->dn) : '';
|
||||||
|
$oc = Factory::create($dn,'objectclass',$request->oc);
|
||||||
|
|
||||||
$ocs = $oc
|
$ocs = $oc
|
||||||
->structural
|
->structural
|
||||||
@ -242,7 +229,7 @@ class HomeController extends Controller
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function entry_password_check(Request $request)
|
public function entry_password_check(Request $request): Collection
|
||||||
{
|
{
|
||||||
$dn = Crypt::decryptString($request->dn);
|
$dn = Crypt::decryptString($request->dn);
|
||||||
$o = config('server')->fetch($dn);
|
$o = config('server')->fetch($dn);
|
||||||
@ -265,10 +252,10 @@ class HomeController extends Controller
|
|||||||
* Show a confirmation to update a DN
|
* Show a confirmation to update a DN
|
||||||
*
|
*
|
||||||
* @param EntryRequest $request
|
* @param EntryRequest $request
|
||||||
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View|\Illuminate\Foundation\Application|\Illuminate\Http\RedirectResponse
|
* @return \Illuminate\Http\RedirectResponse|\Illuminate\View\View
|
||||||
* @throws ObjectNotFoundException
|
* @throws ObjectNotFoundException
|
||||||
*/
|
*/
|
||||||
public function entry_pending_update(EntryRequest $request)
|
public function entry_pending_update(EntryRequest $request): \Illuminate\Http\RedirectResponse|\Illuminate\View\View
|
||||||
{
|
{
|
||||||
$dn = Crypt::decryptString($request->dn);
|
$dn = Crypt::decryptString($request->dn);
|
||||||
|
|
||||||
@ -277,6 +264,8 @@ class HomeController extends Controller
|
|||||||
foreach ($request->except(['_token','dn','userpassword_hash','userpassword']) as $key => $value)
|
foreach ($request->except(['_token','dn','userpassword_hash','userpassword']) as $key => $value)
|
||||||
$o->{$key} = array_filter($value,fn($item)=>! is_null($item));
|
$o->{$key} = array_filter($value,fn($item)=>! is_null($item));
|
||||||
|
|
||||||
|
// @todo Need to handle incoming attributes that were modified by MD5Updates Trait (eg: jpegphoto)
|
||||||
|
|
||||||
// We need to process and encrypt the password
|
// We need to process and encrypt the password
|
||||||
if ($request->userpassword) {
|
if ($request->userpassword) {
|
||||||
$passwords = [];
|
$passwords = [];
|
||||||
@ -312,8 +301,10 @@ class HomeController extends Controller
|
|||||||
* @param EntryRequest $request
|
* @param EntryRequest $request
|
||||||
* @return \Illuminate\Http\RedirectResponse
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
* @throws ObjectNotFoundException
|
* @throws ObjectNotFoundException
|
||||||
|
* @todo When removing an attribute value, from a multi-value attribute, we have a ghost record showing after the update
|
||||||
|
* @todo Need to check when removing a single attribute value, do we have a ghost as well? Might be because we are redirecting with input?
|
||||||
*/
|
*/
|
||||||
public function entry_update(EntryRequest $request)
|
public function entry_update(EntryRequest $request): \Illuminate\Http\RedirectResponse
|
||||||
{
|
{
|
||||||
$dn = Crypt::decryptString($request->dn);
|
$dn = Crypt::decryptString($request->dn);
|
||||||
|
|
||||||
@ -344,17 +335,14 @@ class HomeController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
} catch (LdapRecordException $e) {
|
} catch (LdapRecordException $e) {
|
||||||
$request->flash();
|
return Redirect::to('/')
|
||||||
|
->withInput()
|
||||||
switch ($x=$e->getDetailedError()->getErrorCode()) {
|
->withErrors(sprintf('%s: %s - %s: %s',
|
||||||
case 8:
|
__('LDAP Server Error Code'),
|
||||||
return Redirect::to('/')
|
$e->getDetailedError()->getErrorCode(),
|
||||||
->withInput()
|
__($e->getDetailedError()->getErrorMessage()),
|
||||||
->withErrors(sprintf('%s: %s (%s)',__('LDAP Server Error Code'),$x,__($e->getDetailedError()->getErrorMessage())));
|
$e->getDetailedError()->getDiagnosticMessage(),
|
||||||
|
));
|
||||||
default:
|
|
||||||
abort(599,$e->getDetailedError()->getErrorMessage());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Redirect::to('/')
|
return Redirect::to('/')
|
||||||
@ -368,9 +356,9 @@ class HomeController extends Controller
|
|||||||
*
|
*
|
||||||
* @param Request $request
|
* @param Request $request
|
||||||
* @param Collection|null $old
|
* @param Collection|null $old
|
||||||
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|View
|
* @return \Illuminate\View\View
|
||||||
*/
|
*/
|
||||||
public function frame(Request $request,?Collection $old=NULL): View
|
public function frame(Request $request,?Collection $old=NULL): \Illuminate\View\View
|
||||||
{
|
{
|
||||||
// If our index was not render from a root url, then redirect to it
|
// If our index was not render from a root url, then redirect to it
|
||||||
if (($request->root().'/' !== url()->previous()) && $request->method() === 'POST')
|
if (($request->root().'/' !== url()->previous()) && $request->method() === 'POST')
|
||||||
@ -385,7 +373,9 @@ class HomeController extends Controller
|
|||||||
|
|
||||||
// If we are rendering a DN, rebuild our object
|
// If we are rendering a DN, rebuild our object
|
||||||
$o = config('server')->fetch($key['dn']);
|
$o = config('server')->fetch($key['dn']);
|
||||||
foreach (collect(old())->except(['dn','_token']) as $attr => $value)
|
|
||||||
|
// @todo We need to dynamically exclude request items, so we dont need to add them here
|
||||||
|
foreach (collect(old())->except(['dn','_token','userpassword_hash']) as $attr => $value)
|
||||||
$o->{$attr} = $value;
|
$o->{$attr} = $value;
|
||||||
|
|
||||||
return match ($key['cmd']) {
|
return match ($key['cmd']) {
|
||||||
@ -407,7 +397,7 @@ class HomeController extends Controller
|
|||||||
/**
|
/**
|
||||||
* This is the main page render function
|
* This is the main page render function
|
||||||
*/
|
*/
|
||||||
public function home(Request $request)
|
public function home(Request $request): \Illuminate\View\View
|
||||||
{
|
{
|
||||||
// Did we come here as a result of a redirect
|
// Did we come here as a result of a redirect
|
||||||
return count(old())
|
return count(old())
|
||||||
@ -421,11 +411,11 @@ class HomeController extends Controller
|
|||||||
*
|
*
|
||||||
* @param ImportRequest $request
|
* @param ImportRequest $request
|
||||||
* @param string $type
|
* @param string $type
|
||||||
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View|\Illuminate\Foundation\Application
|
* @return \Illuminate\View\View
|
||||||
* @throws GeneralException
|
* @throws GeneralException
|
||||||
* @throws VersionException
|
* @throws VersionException
|
||||||
*/
|
*/
|
||||||
public function import(ImportRequest $request,string $type)
|
public function import(ImportRequest $request,string $type): \Illuminate\View\View
|
||||||
{
|
{
|
||||||
switch ($type) {
|
switch ($type) {
|
||||||
case 'ldif':
|
case 'ldif':
|
||||||
@ -453,22 +443,6 @@ class HomeController extends Controller
|
|||||||
->with('ldif',htmlspecialchars($x));
|
->with('ldif',htmlspecialchars($x));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function import_frame()
|
|
||||||
{
|
|
||||||
return view('frames.import');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* LDAP Server INFO
|
|
||||||
*
|
|
||||||
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View
|
|
||||||
*/
|
|
||||||
public function info()
|
|
||||||
{
|
|
||||||
return view('frames.info')
|
|
||||||
->with('s',config('server'));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For any incoming request, work out the command and DN involved
|
* For any incoming request, work out the command and DN involved
|
||||||
*
|
*
|
||||||
@ -507,10 +481,10 @@ class HomeController extends Controller
|
|||||||
*
|
*
|
||||||
* @note Our route will validate that types are valid.
|
* @note Our route will validate that types are valid.
|
||||||
* @param Request $request
|
* @param Request $request
|
||||||
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View
|
* @return \Illuminate\View\View
|
||||||
* @throws InvalidUsage
|
* @throws InvalidUsage
|
||||||
*/
|
*/
|
||||||
public function schema_frame(Request $request)
|
public function schema_frame(Request $request): \Illuminate\View\View
|
||||||
{
|
{
|
||||||
// If an invalid key, we'll 404
|
// If an invalid key, we'll 404
|
||||||
if ($request->type && $request->key && (! config('server')->schema($request->type)->has($request->key)))
|
if ($request->type && $request->key && (! config('server')->schema($request->type)->has($request->key)))
|
||||||
@ -536,9 +510,9 @@ class HomeController extends Controller
|
|||||||
* Return the image for the logged in user or anonymous
|
* Return the image for the logged in user or anonymous
|
||||||
*
|
*
|
||||||
* @param Request $request
|
* @param Request $request
|
||||||
* @return mixed
|
* @return \Illuminate\Http\Response
|
||||||
*/
|
*/
|
||||||
public function user_image(Request $request)
|
public function user_image(Request $request): \Illuminate\Http\Response
|
||||||
{
|
{
|
||||||
$image = NULL;
|
$image = NULL;
|
||||||
$content = NULL;
|
$content = NULL;
|
||||||
|
@ -25,6 +25,7 @@ class ApplicationSession
|
|||||||
{
|
{
|
||||||
Config::set('server',new Server);
|
Config::set('server',new Server);
|
||||||
|
|
||||||
|
view()->share('server', Config::get('server'));
|
||||||
view()->share('user', auth()->user() ?: new User);
|
view()->share('user', auth()->user() ?: new User);
|
||||||
|
|
||||||
return $next($request);
|
return $next($request);
|
||||||
|
@ -2,13 +2,14 @@
|
|||||||
|
|
||||||
namespace App\Ldap;
|
namespace App\Ldap;
|
||||||
|
|
||||||
|
use LdapRecord\Configuration\DomainConfiguration;
|
||||||
use LdapRecord\Connection as ConnectionBase;
|
use LdapRecord\Connection as ConnectionBase;
|
||||||
use LdapRecord\LdapInterface;
|
use LdapRecord\LdapInterface;
|
||||||
|
|
||||||
class Connection extends ConnectionBase
|
class Connection extends ConnectionBase
|
||||||
{
|
{
|
||||||
|
|
||||||
public function __construct($config = [], LdapInterface $ldap = null)
|
public function __construct(DomainConfiguration|array $config=[],?LdapInterface $ldap=NULL)
|
||||||
{
|
{
|
||||||
parent::__construct($config,$ldap);
|
parent::__construct($config,$ldap);
|
||||||
|
|
||||||
|
@ -16,7 +16,9 @@ use App\Exceptions\InvalidUsage;
|
|||||||
|
|
||||||
class Entry extends Model
|
class Entry extends Model
|
||||||
{
|
{
|
||||||
|
// Our Attribute objects
|
||||||
private Collection $objects;
|
private Collection $objects;
|
||||||
|
/* @deprecated */
|
||||||
private bool $noObjectAttributes = FALSE;
|
private bool $noObjectAttributes = FALSE;
|
||||||
// For new entries, this is the container that this entry will be stored in
|
// For new entries, this is the container that this entry will be stored in
|
||||||
private string $rdnbase;
|
private string $rdnbase;
|
||||||
@ -82,22 +84,22 @@ class Entry extends Model
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* As attribute values are updated, or new ones created, we need to mirror that
|
* As attribute values are updated, or new ones created, we need to mirror that
|
||||||
* into our $objects
|
* into our $objects. This is called when we $o->key = $value
|
||||||
*
|
*
|
||||||
* @param string $key
|
* @param string $key
|
||||||
* @param mixed $value
|
* @param mixed $value
|
||||||
* @return $this
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function setAttribute(string $key, mixed $value): static
|
public function setAttribute(string $key,mixed $value): static
|
||||||
{
|
{
|
||||||
parent::setAttribute($key,$value);
|
parent::setAttribute($key,$value);
|
||||||
|
|
||||||
$key = $this->normalizeAttributeKey($key);
|
$key = $this->normalizeAttributeKey($key);
|
||||||
|
|
||||||
if ((! $this->objects->get($key)) && $value)
|
$o = $this->objects->get($key) ?: Factory::create($this->dn ?: '',$key,[],Arr::get($this->attributes,'objectclass',[]));
|
||||||
$this->objects->put($key,Factory::create($key,[]));
|
$o->values = collect($this->attributes[$key]);
|
||||||
|
|
||||||
$this->objects->get($key)->value = $this->attributes[$key];
|
$this->objects->put($key,$o);
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
@ -131,16 +133,26 @@ class Entry extends Model
|
|||||||
* Return a key to use for sorting
|
* Return a key to use for sorting
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
* @todo This should be the DN in reverse order
|
|
||||||
*/
|
*/
|
||||||
public function getSortKeyAttribute(): string
|
public function getSortKeyAttribute(): string
|
||||||
{
|
{
|
||||||
return $this->getDn();
|
return collect(explode(',',$this->getDn()))->reverse()->join(',');
|
||||||
}
|
}
|
||||||
|
|
||||||
/* METHODS */
|
/* METHODS */
|
||||||
|
|
||||||
public function addAttribute(string $key,mixed $value): void
|
/**
|
||||||
|
* Add an attribute to this entry, if the attribute already exists, then we'll add the value to the existing item.
|
||||||
|
*
|
||||||
|
* This is primarily used by LDIF imports, where attributes have multiple entries over multiple lines
|
||||||
|
*
|
||||||
|
* @param string $key
|
||||||
|
* @param mixed $value
|
||||||
|
* @return void
|
||||||
|
* @throws AttributeException
|
||||||
|
* @note Attributes added this way dont have objectclass information, and the Model::attributes are not populated
|
||||||
|
*/
|
||||||
|
public function addAttributeItem(string $key,mixed $value): void
|
||||||
{
|
{
|
||||||
// While $value is mixed, it can only be a string
|
// While $value is mixed, it can only be a string
|
||||||
if (! is_string($value))
|
if (! is_string($value))
|
||||||
@ -151,12 +163,10 @@ class Entry extends Model
|
|||||||
if (! config('server')->schema('attributetypes')->has($key))
|
if (! config('server')->schema('attributetypes')->has($key))
|
||||||
throw new AttributeException(sprintf('Schema doesnt have attribute [%s]',$key));
|
throw new AttributeException(sprintf('Schema doesnt have attribute [%s]',$key));
|
||||||
|
|
||||||
if ($x=$this->objects->get($key)) {
|
$o = $this->objects->get($key) ?: Attribute\Factory::create($this->dn ?: '',$key,[]);
|
||||||
$x->addValue($value);
|
$o->addValue($value);
|
||||||
|
|
||||||
} else {
|
$this->objects->put($key,$o);
|
||||||
$this->objects->put($key,Attribute\Factory::create($key,Arr::wrap($value)));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -164,31 +174,36 @@ class Entry extends Model
|
|||||||
*
|
*
|
||||||
* @return Collection
|
* @return Collection
|
||||||
*/
|
*/
|
||||||
public function getAttributesAsObjects(): Collection
|
private function getAttributesAsObjects(): Collection
|
||||||
{
|
{
|
||||||
$result = collect();
|
$result = collect();
|
||||||
|
$entry_oc = Arr::get($this->attributes,'objectclass',[]);
|
||||||
|
|
||||||
foreach ($this->attributes as $attribute => $value) {
|
foreach ($this->attributes as $attribute => $values) {
|
||||||
// If the attribute name has language tags
|
// If the attribute name has tags
|
||||||
$matches = [];
|
$matches = [];
|
||||||
if (preg_match('/^([a-zA-Z]+)(;([a-zA-Z-;]+))+/',$attribute,$matches)) {
|
if (preg_match('/^([a-zA-Z]+)(;([a-zA-Z-;]+))+/',$attribute,$matches)) {
|
||||||
$attribute = $matches[1];
|
$attribute = $matches[1];
|
||||||
|
|
||||||
// If the attribute doesnt exist we'll create it
|
// If the attribute doesnt exist we'll create it
|
||||||
$o = Arr::get($result,$attribute,Factory::create($attribute,[]));
|
$o = Arr::get(
|
||||||
$o->setLangTag($matches[3],$value);
|
$result,
|
||||||
|
$attribute,
|
||||||
|
Factory::create(
|
||||||
|
$this->dn,
|
||||||
|
$attribute,
|
||||||
|
Arr::get($this->original,$attribute,[]),
|
||||||
|
$entry_oc,
|
||||||
|
));
|
||||||
|
$o->setLangTag($matches[3],$values);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
$o = Factory::create($attribute,$value);
|
$o = Factory::create($this->dn,$attribute,Arr::get($this->original,$attribute,[]),$entry_oc);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! $result->has($attribute)) {
|
if (! $result->has($attribute)) {
|
||||||
// Set the rdn flag
|
// Store our new values to know if this attribute has changed
|
||||||
if (preg_match('/^'.$attribute.'=/i',$this->dn))
|
$o->values = collect($values);
|
||||||
$o->setRDN();
|
|
||||||
|
|
||||||
// Store our original value to know if this attribute has changed
|
|
||||||
$o->oldValues(Arr::get($this->original,$attribute,[]));
|
|
||||||
|
|
||||||
$result->put($attribute,$o);
|
$result->put($attribute,$o);
|
||||||
}
|
}
|
||||||
@ -297,8 +312,8 @@ class Entry extends Model
|
|||||||
|
|
||||||
private function getRDNObject(): Attribute\RDN
|
private function getRDNObject(): Attribute\RDN
|
||||||
{
|
{
|
||||||
$o = new Attribute\RDN('dn',['']);
|
$o = new Attribute\RDN('','dn',['']);
|
||||||
// @todo for an existing object, return the base.
|
// @todo for an existing object, rdnbase would be null, so dynamically get it from the DN.
|
||||||
$o->setBase($this->rdnbase);
|
$o->setBase($this->rdnbase);
|
||||||
$o->setAttributes($this->getAvailableAttributes()->filter(fn($item)=>$item->required));
|
$o->setAttributes($this->getAvailableAttributes()->filter(fn($item)=>$item->required));
|
||||||
|
|
||||||
@ -422,6 +437,7 @@ class Entry extends Model
|
|||||||
* Dont convert our $this->attributes to $this->objects when creating a new Entry::class
|
* Dont convert our $this->attributes to $this->objects when creating a new Entry::class
|
||||||
*
|
*
|
||||||
* @return $this
|
* @return $this
|
||||||
|
* @deprecated
|
||||||
*/
|
*/
|
||||||
public function noObjectAttributes(): static
|
public function noObjectAttributes(): static
|
||||||
{
|
{
|
||||||
|
@ -14,7 +14,7 @@ use LdapRecord\Models\Model as LdapRecord;
|
|||||||
*/
|
*/
|
||||||
class LoginObjectclassRule implements Rule
|
class LoginObjectclassRule implements Rule
|
||||||
{
|
{
|
||||||
public function passes(LdapRecord $user, Eloquent $model = null): bool
|
public function passes(LdapRecord $user,?Eloquent $model=NULL): bool
|
||||||
{
|
{
|
||||||
if ($x=config('pla.login.objectclass')) {
|
if ($x=config('pla.login.objectclass')) {
|
||||||
return count(array_intersect($user->objectclass,$x));
|
return count(array_intersect($user->objectclass,$x));
|
||||||
|
@ -11,8 +11,8 @@ trait MD5Updates
|
|||||||
{
|
{
|
||||||
public function isDirty(): bool
|
public function isDirty(): bool
|
||||||
{
|
{
|
||||||
foreach ($this->values->diff($this->oldValues) as $key => $value)
|
foreach ($this->values->diff($this->values_old) as $key => $value)
|
||||||
if (md5(Arr::get($this->oldValues,$key)) !== $value)
|
if (md5(Arr::get($this->values_old,$key)) !== $value)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -11,17 +11,15 @@ use App\Classes\LDAP\Attribute as LDAPAttribute;
|
|||||||
|
|
||||||
class AttributeType extends Component
|
class AttributeType extends Component
|
||||||
{
|
{
|
||||||
public Collection $oc;
|
private LDAPAttribute $o;
|
||||||
public LDAPAttribute $o;
|
private bool $new;
|
||||||
public bool $new;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new component instance.
|
* Create a new component instance.
|
||||||
*/
|
*/
|
||||||
public function __construct(LDAPAttribute $o,bool $new=FALSE,?Collection $oc=NULL)
|
public function __construct(LDAPAttribute $o,bool $new=FALSE)
|
||||||
{
|
{
|
||||||
$this->o = $o;
|
$this->o = $o;
|
||||||
$this->oc = $oc;
|
|
||||||
$this->new = $new;
|
$this->new = $new;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,7 +30,6 @@ class AttributeType extends Component
|
|||||||
{
|
{
|
||||||
return view('components.attribute-type')
|
return view('components.attribute-type')
|
||||||
->with('o',$this->o)
|
->with('o',$this->o)
|
||||||
->with('oc',$this->oc)
|
|
||||||
->with('new',$this->new);
|
->with('new',$this->new);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1 +1 @@
|
|||||||
v2.0.2-rel
|
v2.0.3-dev
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
<div class="h5 modal-title text-center">
|
<div class="h5 modal-title text-center">
|
||||||
<h4 class="mt-2">
|
<h4 class="mt-2">
|
||||||
<div class="app-logo mx-auto mb-3"><img class="w-75" src="{{ url('images/logo-h-lg.png') }}"></div>
|
<div class="app-logo mx-auto mb-3"><img class="w-75" src="{{ url('images/logo-h-lg.png') }}"></div>
|
||||||
<small>@lang('Sign in to') <strong>{{ config('server')->name }}</strong></small>
|
<small>@lang('Sign in to') <strong>{{ $server->name }}</strong></small>
|
||||||
</h4>
|
</h4>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
<div class="scrollbar-sidebar">
|
<div class="scrollbar-sidebar">
|
||||||
<div class="app-sidebar__inner">
|
<div class="app-sidebar__inner">
|
||||||
<ul class="vertical-nav-menu">
|
<ul class="vertical-nav-menu">
|
||||||
<li class="app-sidebar__heading">{{ config('server')->name }}</li>
|
<li class="app-sidebar__heading">{{ $server->name }}</li>
|
||||||
<li>
|
<li>
|
||||||
<i id="treeicon" class="metismenu-icon fa-fw fas fa-sitemap"></i>
|
<i id="treeicon" class="metismenu-icon fa-fw fas fa-sitemap"></i>
|
||||||
<span class="f16" id="tree"></span>
|
<span class="f16" id="tree"></span>
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<!-- $o=Binary\JpegPhoto::class -->
|
<!-- $o=Binary\JpegPhoto::class -->
|
||||||
<x-attribute.layout :edit="$edit" :new="false" :o="$o">
|
<x-attribute.layout :edit="$edit" :new="false" :o="$o">
|
||||||
<table class="table table-borderless p-0 m-0">
|
<table class="table table-borderless p-0 m-0">
|
||||||
@foreach (($old ? $o->old_values : $o->values) as $value)
|
@foreach ($o->values_old as $value)
|
||||||
<tr>
|
<tr>
|
||||||
@switch ($x=$f->buffer($value,FILEINFO_MIME_TYPE))
|
@switch ($x=$f->buffer($value,FILEINFO_MIME_TYPE))
|
||||||
@case('image/jpeg')
|
@case('image/jpeg')
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<!-- $o=Internal\Timestamp::class -->
|
<!-- $o=Internal::class -->
|
||||||
@foreach (old($o->name_lc,$o->values) as $value)
|
@foreach (old($o->name_lc,$o->values) as $value)
|
||||||
@if($loop->index)<br>@endif
|
@if($loop->index)<br>@endif
|
||||||
{{ $value }}
|
{{ $value }}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
|
<!-- @todo We are not handling redirect backs yet with updated passwords -->
|
||||||
<!-- $o=Password::class -->
|
<!-- $o=Password::class -->
|
||||||
<x-attribute.layout :edit="$edit ?? FALSE" :new="$new ?? FALSE" :o="$o">
|
<x-attribute.layout :edit="$edit ?? FALSE" :new="$new ?? FALSE" :o="$o">
|
||||||
@foreach($o->values as $value)
|
@foreach($o->values_old as $value)
|
||||||
@if($edit)
|
@if($edit)
|
||||||
<div class="input-group has-validation mb-3">
|
<div class="input-group has-validation mb-3">
|
||||||
<input type="password" @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="{{ md5($value) }}" @readonly(true)>
|
<input type="password" @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="{{ md5($value) }}" @readonly(true)>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<div class="row pt-2">
|
<div class="row pt-2">
|
||||||
<div @class(['col-1','d-none'=>(! $edit) && (! ($detail ?? true))])></div>
|
<div @class(['col-1','d-none'=>(! $edit) && (! ($detail ?? false))])></div>
|
||||||
<div class="col-10 p-2">
|
<div class="col-10">
|
||||||
<attribute id="{{ $o->name }}">
|
<attribute id="{{ $o->name }}">
|
||||||
{{ $slot }}
|
{{ $slot }}
|
||||||
</attribute>
|
</attribute>
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
|
<!-- @todo We are not handling redirect backs yet with updated passwords -->
|
||||||
<!-- $o=Password::class -->
|
<!-- $o=Password::class -->
|
||||||
<x-attribute.layout :edit="$edit ?? FALSE" :new="$new ?? FALSE" :o="$o">
|
<x-attribute.layout :edit="$edit ?? FALSE" :new="$new ?? FALSE" :o="$o">
|
||||||
@foreach($o->values as $value)
|
@foreach($o->values_old as $value)
|
||||||
@if($edit)
|
@if($edit)
|
||||||
<div class="input-group has-validation mb-3">
|
<div class="input-group has-validation mb-3">
|
||||||
<x-form.select id="userpassword_hash_{{$loop->index}}" name="userpassword_hash[]" :value="$o->hash($value)->id()" :options="$helpers" allowclear="false" :disabled="true"/>
|
<x-form.select id="userpassword_hash_{{$loop->index}}" name="userpassword_hash[]" :value="$o->hash($value)->id()" :options="$helpers" allowclear="false" :disabled="true"/>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<!-- $o=RDN::class -->
|
<!-- $o=RDN::class -->
|
||||||
<x-attribute.layout :edit="$edit ?? FALSE" :new="$new ?? FALSE" :o="$o">
|
<x-attribute.layout :edit="$edit ?? FALSE" :new="$new ?? FALSE" :o="$o">
|
||||||
@foreach($o->values as $value)
|
@foreach(($o->values->count() ? $o->values : ['']) as $value)
|
||||||
@if($edit)
|
@if($edit)
|
||||||
<div class="input-group has-validation mb-3">
|
<div class="input-group has-validation mb-3">
|
||||||
<select class="form-select @error('rdn')is-invalid @enderror" id="rdn" name="rdn">
|
<select class="form-select @error('rdn')is-invalid @enderror" id="rdn" name="rdn">
|
||||||
@ -38,23 +38,23 @@
|
|||||||
rdn_attr = $('select#rdn').val();
|
rdn_attr = $('select#rdn').val();
|
||||||
|
|
||||||
if (rdn_attr) {
|
if (rdn_attr) {
|
||||||
$('#'+rdn_attr).find('input').attr('readonly',true);
|
$('#'+rdn_attr).find('input').first().attr('readonly',true);
|
||||||
set_rdn_value();
|
set_rdn_value();
|
||||||
}
|
}
|
||||||
|
|
||||||
function set_rdn_value() {
|
function set_rdn_value() {
|
||||||
if (rdn_attr && rdn_value_set)
|
if (rdn_attr && rdn_value_set)
|
||||||
$('#'+rdn_attr).find('input').val($('input#rdn_value').val());
|
$('#'+rdn_attr).find('input').first().val($('input#rdn_value').val());
|
||||||
}
|
}
|
||||||
|
|
||||||
$('select#rdn').on('change',function() {
|
$('select#rdn').on('change',function() {
|
||||||
// if rdn_attr is already set (and its now different), remove read only and clear value
|
// if rdn_attr is already set (and its now different), remove read only and clear value
|
||||||
if (rdn_attr)
|
if (rdn_attr)
|
||||||
$('#'+rdn_attr).find('input').attr('readonly',false).val('');
|
$('#'+rdn_attr).find('input').first().attr('readonly',false).val('');
|
||||||
|
|
||||||
// set RDN attribute read-only
|
// set RDN attribute read-only
|
||||||
if (rdn_attr = $(this).val())
|
if (rdn_attr = $(this).val())
|
||||||
$('#'+rdn_attr).find('input').attr('readonly',true).val('');
|
$('#'+rdn_attr).find('input').first().attr('readonly',true).val('');
|
||||||
|
|
||||||
set_rdn_value();
|
set_rdn_value();
|
||||||
})
|
})
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
<td>BaseDN(s)</td>
|
<td>BaseDN(s)</td>
|
||||||
<td>
|
<td>
|
||||||
<table class="table table-sm table-borderless">
|
<table class="table table-sm table-borderless">
|
||||||
@foreach(\App\Classes\LDAP\Server::baseDNs()->sort(function($item) { return $item->sortKey; }) as $item)
|
@foreach($server->baseDNs()->sort(fn($item)=>$item->sort_key) as $item)
|
||||||
<tr>
|
<tr>
|
||||||
<td class="ps-0">{{ $item->getDn() }}</td>
|
<td class="ps-0">{{ $item->getDn() }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
@ -36,7 +36,13 @@
|
|||||||
<!-- Schema DN -->
|
<!-- Schema DN -->
|
||||||
<tr>
|
<tr>
|
||||||
<td>Schema DN</td>
|
<td>Schema DN</td>
|
||||||
<td>{{ \App\Classes\LDAP\Server::schemaDN() }}</td>
|
<td>{{ $server->schemaDN() }}</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<!-- Schema DN -->
|
||||||
|
<tr>
|
||||||
|
<td>Root URL</td>
|
||||||
|
<td>{{ request()->root() }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
@ -106,6 +106,24 @@
|
|||||||
@endif
|
@endif
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>@lang('Required by ObjectClasses')</td>
|
||||||
|
<td>
|
||||||
|
@if ($o->required_by_object_classes->count())
|
||||||
|
@foreach ($o->required_by_object_classes as $class => $structural)
|
||||||
|
@if($structural)
|
||||||
|
<strong>
|
||||||
|
@endif
|
||||||
|
<a class="objectclass" id="{{ strtolower($class) }}" href="#{{ strtolower($class) }}">{{ $class }}</a>
|
||||||
|
@if($structural)
|
||||||
|
</strong>
|
||||||
|
@endif
|
||||||
|
@endforeach
|
||||||
|
@else
|
||||||
|
@lang('(none)')
|
||||||
|
@endif
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>@lang('Force as MAY by config')</td><td><strong>@lang($o->forced_as_may ? 'Yes' : 'No')</strong></td>
|
<td>@lang('Force as MAY by config')</td><td><strong>@lang($o->forced_as_may ? 'Yes' : 'No')</strong></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
@extends('layouts.dn')
|
@extends('layouts.dn')
|
||||||
|
|
||||||
@section('page_title')
|
@section('page_title')
|
||||||
@include('fragment.dn.header',['o'=>($oo=config('server')->fetch(old('container',$container)))])
|
@include('fragment.dn.header',['o'=>($oo=$server->fetch(old('container',$container)))])
|
||||||
@endsection
|
@endsection
|
||||||
|
|
||||||
@section('main-content')
|
@section('main-content')
|
||||||
@ -30,7 +30,7 @@
|
|||||||
id="objectclass"
|
id="objectclass"
|
||||||
name="objectclass[]"
|
name="objectclass[]"
|
||||||
:label="__('Select a Structural ObjectClass...')"
|
:label="__('Select a Structural ObjectClass...')"
|
||||||
:options="($oc=config('server')->schema('objectclasses'))
|
:options="($oc=$server->schema('objectclasses'))
|
||||||
->filter(fn($item)=>$item->isStructural())
|
->filter(fn($item)=>$item->isStructural())
|
||||||
->sortBy(fn($item)=>$item->name_lc)
|
->sortBy(fn($item)=>$item->name_lc)
|
||||||
->map(fn($item)=>['id'=>$item->name,'value'=>$item->name])"
|
->map(fn($item)=>['id'=>$item->name,'value'=>$item->name])"
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
@extends('layouts.dn')
|
@extends('layouts.dn')
|
||||||
|
|
||||||
@section('page_title')
|
@section('page_title')
|
||||||
@include('fragment.dn.header',['o'=>($o ?? $o=config('server')->fetch($dn))])
|
@include('fragment.dn.header',['o'=>($o ?? $o=$server->fetch($dn))])
|
||||||
@endsection
|
@endsection
|
||||||
|
|
||||||
@section('main-content')
|
@section('main-content')
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
<table class="table table-borderless">
|
<table class="table table-borderless">
|
||||||
<tr>
|
<tr>
|
||||||
<td style="border-radius: 5px;"><div class="page-title-icon f32"><i class="fas fa-upload"></i></div></td>
|
<td style="border-radius: 5px;"><div class="page-title-icon f32"><i class="fas fa-upload"></i></div></td>
|
||||||
<td class="top text-start align-text-top p-0 pt-2"><strong>@lang('LDIF Import')</strong><br><small>@lang('To Server') <strong>{{ config('server')->name }}</strong></small></td>
|
<td class="top text-start align-text-top p-2"><strong>@lang('LDIF Import')</strong><br><small>@lang('To Server') <strong>{{ $server->name }}</strong></small></td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
@endsection
|
@endsection
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<table class="table table-borderless">
|
<table class="table table-borderless">
|
||||||
<tr>
|
<tr>
|
||||||
<td style="border-radius: 5px;"><div class="page-title-icon f32"><i class="fas fa-upload"></i></div></td>
|
<td style="border-radius: 5px;"><div class="page-title-icon f32"><i class="fas fa-upload"></i></div></td>
|
||||||
<td class="top text-start align-text-top p-0 pt-2"><strong>@lang('LDIF Import Result')</strong><br><small>@lang('To Server') <strong>{{ config('server')->name }}</strong></small></td>
|
<td class="top text-start align-text-top p-0 pt-2"><strong>@lang('LDIF Import Result')</strong><br><small>@lang('To Server') <strong>{{ $server->name }}</strong></small></td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
@endsection
|
@endsection
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
<table class="table table-borderless">
|
<table class="table table-borderless">
|
||||||
<tr>
|
<tr>
|
||||||
<td style="border-radius: 5px;"><div class="page-title-icon f32"><i class="fas fa-info"></i></div></td>
|
<td style="border-radius: 5px;"><div class="page-title-icon f32"><i class="fas fa-info"></i></div></td>
|
||||||
<td class="top text-end align-text-top p-0 pt-2"><strong>@lang('Server Info')</strong><br><small>{{ $s->rootDSE()->entryuuid[0] ?? '' }}</small></td>
|
<td class="top text-end align-text-top p-2"><strong>@lang('Server Info')</strong><br><small>{{ $server->rootDSE()->entryuuid[0] ?? '' }}</small></td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
@endsection
|
@endsection
|
||||||
@ -13,10 +13,10 @@
|
|||||||
<div class="main-card mb-3 card">
|
<div class="main-card mb-3 card">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<table class="table">
|
<table class="table">
|
||||||
@foreach ($s->rootDSE()->getObjects() as $attribute => $ao)
|
@foreach ($server->rootDSE()->getObjects() as $attribute => $ao)
|
||||||
<tr>
|
<tr>
|
||||||
<th class="w-25">
|
<th class="w-25">
|
||||||
{!! ($x=$s->schema('attributetypes',$attribute))
|
{!! ($x=$server->schema('attributetypes',$attribute))
|
||||||
? sprintf('<a class="attributetype" id="strtolower(%s)" href="%s">%s</a>',$x->name_lc,url('schema/attributetypes',$x->name_lc),$x->name)
|
? sprintf('<a class="attributetype" id="strtolower(%s)" href="%s">%s</a>',$x->name_lc,url('schema/attributetypes',$x->name_lc),$x->name)
|
||||||
: $attribute !!}
|
: $attribute !!}
|
||||||
</th>
|
</th>
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<table class="table table-borderless">
|
<table class="table table-borderless">
|
||||||
<tr>
|
<tr>
|
||||||
<td style="border-radius: 5px;"><div class="page-title-icon f32"><i class="fas fa-fingerprint"></i></div></td>
|
<td style="border-radius: 5px;"><div class="page-title-icon f32"><i class="fas fa-fingerprint"></i></div></td>
|
||||||
<td class="top text-end align-text-top p-0 pt-2"><strong>{{ Server::schemaDN() }}</strong></td>
|
<td class="top text-end align-text-top p-2"><strong>{{ Server::schemaDN() }}</strong></td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
@endsection
|
@endsection
|
||||||
|
@ -29,9 +29,9 @@
|
|||||||
</thead>
|
</thead>
|
||||||
|
|
||||||
<tbody>
|
<tbody>
|
||||||
@foreach ($o->getAttributesAsObjects()->filter(fn($item)=>$item->isDirty()) as $key => $oo)
|
@foreach ($o->getObjects()->filter(fn($item)=>$item->isDirty()) as $key => $oo)
|
||||||
<tr>
|
<tr>
|
||||||
<th rowspan="{{ $x=max($oo->values->keys()->max(),$oo->old_values->keys()->max())+1}}">
|
<th rowspan="{{ $x=max($oo->values->keys()->max(),$oo->values_old->keys()->max())+1}}">
|
||||||
<abbr title="{{ $oo->description }}">{{ $oo->name }}</abbr>
|
<abbr title="{{ $oo->description }}">{{ $oo->name }}</abbr>
|
||||||
</th>
|
</th>
|
||||||
@for($xx=0;$xx<$x;$xx++)
|
@for($xx=0;$xx<$x;$xx++)
|
||||||
|
@ -31,10 +31,10 @@ Route::get('logout',[LoginController::class,'logout']);
|
|||||||
Route::controller(HomeController::class)->group(function() {
|
Route::controller(HomeController::class)->group(function() {
|
||||||
Route::middleware(AllowAnonymous::class)->group(function() {
|
Route::middleware(AllowAnonymous::class)->group(function() {
|
||||||
Route::get('/','home');
|
Route::get('/','home');
|
||||||
Route::get('info','info');
|
Route::view('info','frames.info');
|
||||||
Route::get('debug','debug');
|
Route::view('debug','debug');
|
||||||
Route::post('frame','frame');
|
Route::post('frame','frame');
|
||||||
Route::get('import','import_frame');
|
Route::view('import','frames.import');
|
||||||
Route::get('schema','schema_frame');
|
Route::get('schema','schema_frame');
|
||||||
|
|
||||||
Route::group(['prefix'=>'user'],function() {
|
Route::group(['prefix'=>'user'],function() {
|
||||||
|
24
tests/server/openldap/data/04-z_usercert.ldif
Normal file
24
tests/server/openldap/data/04-z_usercert.ldif
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
|
||||||
|
dn: uid=usercert,dc=example.com
|
||||||
|
cn: cn
|
||||||
|
gidNumber: 1111
|
||||||
|
homeDirectory: /home
|
||||||
|
objectClass: account
|
||||||
|
objectClass: posixAccount
|
||||||
|
objectClass: pkiUser
|
||||||
|
uid: usercert
|
||||||
|
uidNumber: 111
|
||||||
|
usercertificate;binary:: MIIC2TCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQQFADBGMQswCQYD
|
||||||
|
VQQGEwJJVDENMAsGA1UEChMESU5GTjESMBAGA1UECxMJQXV0aG9yaXR5MRQwEgYDVQQDEwtJTkZO
|
||||||
|
IENBICgyKTAeFw05OTA2MjMxMTE2MDdaFw0wMzA4MDExMTE2MDdaMEYxCzAJBgNVBAYTAklUMQ0w
|
||||||
|
CwYDVQQKEwRJTkZOMRIwEAYDVQQLEwlBdXRob3JpdHkxFDASBgNVBAMTC0lORk4gQ0EgKDIpMIGf
|
||||||
|
MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrHdRKJsobcjXz/OsGjyq8v73DbggG3JCGrQZ9f1Vm
|
||||||
|
9RrIWJPwggczqgxwWL6JLPKglxbUjAtUxiZm3fw2kX7FGMUq5JaN/Pk2PT4ExA7bYLnbLGZ9jKJs
|
||||||
|
Dh4bNOKrGRIxRO9Ff+YwmH8EQdoVpSRFbBpNnoDIkHLc4DtzB+B4wwIDAQABo4HWMIHTMAwGA1Ud
|
||||||
|
EwQFMAMBAf8wHQYDVR0OBBYEFK3QjOXGc4j9LqYEYTn9WvSRAcusMG4GA1UdIwRnMGWAFK3QjOXG
|
||||||
|
c4j9LqYEYTn9WvSRAcusoUqkSDBGMQswCQYDVQQGEwJJVDENMAsGA1UEChMESU5GTjESMBAGA1UE
|
||||||
|
CxMJQXV0aG9yaXR5MRQwEgYDVQQDEwtJTkZOIENBICgyKYIBADALBgNVHQ8EBAMCAQYwEQYJYIZI
|
||||||
|
AYb4QgEBBAQDAgAHMAkGA1UdEQQCMAAwCQYDVR0SBAIwADANBgkqhkiG9w0BAQQFAAOBgQCDs5b1
|
||||||
|
jmbIYVq2epd5iDjQ109SJ/V7b6DFw2NIl8CWeDPOOjL1E5M8dnlmCDeTR2TlBxqUZaBBJZPqzFdv
|
||||||
|
xpxqsHC0HfkCXAnUe5MaefFNAH9WbxoB/A2pkXtT6WGWed+QsL5wyKJaO4oD9UD5T+x12aGsHcsD
|
||||||
|
Cy3EVEaGEOl+/A==
|
Loading…
x
Reference in New Issue
Block a user