Compare commits
No commits in common. "f19c5594d52355b92b44cc2f3043a98515da2668" and "db4b90183f012b8fce07bfca0b30d944b95aee00" have entirely different histories.
f19c5594d5
...
db4b90183f
@ -3,7 +3,6 @@
|
|||||||
namespace App\Classes\LDAP;
|
namespace App\Classes\LDAP;
|
||||||
|
|
||||||
use Illuminate\Contracts\View\View;
|
use Illuminate\Contracts\View\View;
|
||||||
use Illuminate\Support\Arr;
|
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
use App\Classes\LDAP\Schema\AttributeType;
|
use App\Classes\LDAP\Schema\AttributeType;
|
||||||
@ -11,11 +10,10 @@ use App\Classes\LDAP\Schema\AttributeType;
|
|||||||
/**
|
/**
|
||||||
* Represents an attribute of an LDAP Object
|
* Represents an attribute of an LDAP Object
|
||||||
*/
|
*/
|
||||||
class Attribute implements \Countable, \ArrayAccess, \Iterator
|
class Attribute implements \Countable, \ArrayAccess
|
||||||
{
|
{
|
||||||
// Attribute Name
|
// Attribute Name
|
||||||
protected string $name;
|
protected string $name;
|
||||||
private int $counter = 0;
|
|
||||||
|
|
||||||
protected ?AttributeType $schema = NULL;
|
protected ?AttributeType $schema = NULL;
|
||||||
|
|
||||||
@ -175,31 +173,6 @@ class Attribute implements \Countable, \ArrayAccess, \Iterator
|
|||||||
$this->values->push($value);
|
$this->values->push($value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function current(): mixed
|
|
||||||
{
|
|
||||||
return $this->values->get($this->counter);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function next(): void
|
|
||||||
{
|
|
||||||
$this->counter++;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function key(): mixed
|
|
||||||
{
|
|
||||||
return $this->counter;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function valid(): bool
|
|
||||||
{
|
|
||||||
return $this->values->has($this->counter);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function rewind(): void
|
|
||||||
{
|
|
||||||
$this->counter = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function count(): int
|
public function count(): int
|
||||||
{
|
{
|
||||||
return $this->values->count();
|
return $this->values->count();
|
||||||
@ -207,7 +180,7 @@ class Attribute implements \Countable, \ArrayAccess, \Iterator
|
|||||||
|
|
||||||
public function offsetExists(mixed $offset): bool
|
public function offsetExists(mixed $offset): bool
|
||||||
{
|
{
|
||||||
return ! is_null($this->values->has($offset));
|
return ! is_null($this->values->get($offset));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function offsetGet(mixed $offset): mixed
|
public function offsetGet(mixed $offset): mixed
|
||||||
@ -260,8 +233,10 @@ class Attribute implements \Countable, \ArrayAccess, \Iterator
|
|||||||
*/
|
*/
|
||||||
public function isDirty(): bool
|
public function isDirty(): bool
|
||||||
{
|
{
|
||||||
return ($this->oldValues->count() !== $this->values->count())
|
if ($this->oldValues->count() !== $this->values->count())
|
||||||
|| ($this->values->diff($this->oldValues)->count() !== 0);
|
return TRUE;
|
||||||
|
|
||||||
|
return $this->values->diff($this->oldValues)->count() !== 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function oldValues(array $array): void
|
public function oldValues(array $array): void
|
||||||
@ -272,9 +247,9 @@ class Attribute implements \Countable, \ArrayAccess, \Iterator
|
|||||||
/**
|
/**
|
||||||
* Display the attribute value
|
* Display the attribute value
|
||||||
*
|
*
|
||||||
* @param bool $edit Render an edit form
|
* @param bool $edit
|
||||||
* @param bool $old Use old value
|
* @param bool $old
|
||||||
* @param bool $new Enable adding values
|
* @param bool $new
|
||||||
* @return View
|
* @return View
|
||||||
*/
|
*/
|
||||||
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
|
||||||
@ -286,16 +261,6 @@ class Attribute implements \Countable, \ArrayAccess, \Iterator
|
|||||||
->with('new',$new);
|
->with('new',$new);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function render_item_old(int $key): ?string
|
|
||||||
{
|
|
||||||
return Arr::get($this->old_values,$key);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function render_item_new(int $key): ?string
|
|
||||||
{
|
|
||||||
return Arr::get($this->values,$key);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the objectclasses that require this attribute
|
* Set the objectclasses that require this attribute
|
||||||
*
|
*
|
||||||
|
@ -14,6 +14,13 @@ final class JpegPhoto extends Binary
|
|||||||
{
|
{
|
||||||
use MD5Updates;
|
use MD5Updates;
|
||||||
|
|
||||||
|
public function __construct(string $name,array $values)
|
||||||
|
{
|
||||||
|
parent::__construct($name,$values);
|
||||||
|
|
||||||
|
$this->internal = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
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
|
||||||
{
|
{
|
||||||
return view('components.attribute.binary.jpegphoto')
|
return view('components.attribute.binary.jpegphoto')
|
||||||
|
@ -36,7 +36,7 @@ final class ObjectClass extends Attribute
|
|||||||
*/
|
*/
|
||||||
public function isStructural(string $value): bool
|
public function isStructural(string $value): bool
|
||||||
{
|
{
|
||||||
return $this->structural->contains($value);
|
return $this->structural->search($value) !== FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
||||||
|
@ -3,10 +3,7 @@
|
|||||||
namespace App\Classes\LDAP\Attribute;
|
namespace App\Classes\LDAP\Attribute;
|
||||||
|
|
||||||
use Illuminate\Contracts\View\View;
|
use Illuminate\Contracts\View\View;
|
||||||
use Illuminate\Support\Arr;
|
|
||||||
use Illuminate\Support\Collection;
|
|
||||||
|
|
||||||
use App\Classes\LDAP\Attribute\Password\Base;
|
|
||||||
use App\Classes\LDAP\Attribute;
|
use App\Classes\LDAP\Attribute;
|
||||||
use App\Traits\MD5Updates;
|
use App\Traits\MD5Updates;
|
||||||
|
|
||||||
@ -16,52 +13,6 @@ use App\Traits\MD5Updates;
|
|||||||
final class Password extends Attribute
|
final class Password extends Attribute
|
||||||
{
|
{
|
||||||
use MD5Updates;
|
use MD5Updates;
|
||||||
private const password_helpers = 'Classes/LDAP/Attribute/Password';
|
|
||||||
public const commands = 'App\\Classes\\LDAP\\Attribute\\Password\\';
|
|
||||||
|
|
||||||
private static function helpers(): Collection
|
|
||||||
{
|
|
||||||
$helpers = collect();
|
|
||||||
|
|
||||||
foreach (preg_grep('/^([^.])/',scandir(app_path(self::password_helpers))) as $file) {
|
|
||||||
if (($file === 'Base.php') || (! str_ends_with(strtolower($file),'.php')))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
$class = self::commands.preg_replace('/\.php$/','',$file);
|
|
||||||
if ($helpers->count())
|
|
||||||
$helpers->push('');
|
|
||||||
|
|
||||||
$helpers = $helpers
|
|
||||||
->merge([$class::id()=>$class]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $helpers;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the object that will process a password
|
|
||||||
*
|
|
||||||
* @param string $id
|
|
||||||
* @return Base|null
|
|
||||||
*/
|
|
||||||
public static function hash(string $id): ?Attribute\Password\Base
|
|
||||||
{
|
|
||||||
return ($helpers=static::helpers())->has($id) ? new ($helpers->get($id)) : NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Given an LDAP password syntax {xxx}yyyyyy, this function will return xxx
|
|
||||||
*
|
|
||||||
* @param string $password
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public static function hash_id(string $password): string
|
|
||||||
{
|
|
||||||
$m = [];
|
|
||||||
preg_match('/^{([A-Z]+)}(.*)$/',$password,$m);
|
|
||||||
|
|
||||||
return Arr::get($m,1,'Clear');
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
||||||
{
|
{
|
||||||
@ -69,17 +20,6 @@ final class Password extends Attribute
|
|||||||
->with('o',$this)
|
->with('o',$this)
|
||||||
->with('edit',$edit)
|
->with('edit',$edit)
|
||||||
->with('old',$old)
|
->with('old',$old)
|
||||||
->with('new',$new)
|
->with('new',$new);
|
||||||
->with('helpers',static::helpers()->map(fn($item,$key)=>['id'=>$key,'value'=>$key]));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function render_item_old(int $key): ?string
|
|
||||||
{
|
|
||||||
return Arr::get($this->oldValues,$key) ? str_repeat('x',8) : NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function render_item_new(int $key): ?string
|
|
||||||
{
|
|
||||||
return Arr::get($this->values,$key) ? str_repeat('x',8) : NULL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,14 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Classes\LDAP\Attribute\Password;
|
|
||||||
|
|
||||||
abstract class Base
|
|
||||||
{
|
|
||||||
abstract public function compare(string $source,string $compare): bool;
|
|
||||||
abstract public function encode(string $password): string;
|
|
||||||
|
|
||||||
public static function id(): string
|
|
||||||
{
|
|
||||||
return static::key;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,18 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Classes\LDAP\Attribute\Password;
|
|
||||||
|
|
||||||
final class Clear extends Base
|
|
||||||
{
|
|
||||||
public const key = 'Clear';
|
|
||||||
|
|
||||||
public function compare(string $source,string $compare): bool
|
|
||||||
{
|
|
||||||
return $source === $compare;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function encode(string $password): string
|
|
||||||
{
|
|
||||||
return $password;
|
|
||||||
}
|
|
||||||
}
|
|
@ -324,7 +324,7 @@ final class AttributeType extends Base {
|
|||||||
*/
|
*/
|
||||||
public function addRequiredByObjectClass(string $name): void
|
public function addRequiredByObjectClass(string $name): void
|
||||||
{
|
{
|
||||||
if (! $this->required_by_object_classes->contains($name))
|
if ($this->required_by_object_classes->search($name) === FALSE)
|
||||||
$this->required_by_object_classes->push($name);
|
$this->required_by_object_classes->push($name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -336,7 +336,7 @@ final class AttributeType extends Base {
|
|||||||
*/
|
*/
|
||||||
public function addUsedInObjectClass(string $name): void
|
public function addUsedInObjectClass(string $name): void
|
||||||
{
|
{
|
||||||
if (! $this->used_in_object_classes->contains($name))
|
if ($this->used_in_object_classes->search($name) === FALSE)
|
||||||
$this->used_in_object_classes->push($name);
|
$this->used_in_object_classes->push($name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,7 +115,7 @@ final class MatchingRule extends Base {
|
|||||||
{
|
{
|
||||||
$name = trim($name);
|
$name = trim($name);
|
||||||
|
|
||||||
if (! $this->used_by_attrs->contains($name))
|
if ($this->used_by_attrs->search($name) === FALSE)
|
||||||
$this->used_by_attrs->push($name);
|
$this->used_by_attrs->push($name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -241,7 +241,7 @@ final class ObjectClass extends Base
|
|||||||
*/
|
*/
|
||||||
public function addChildObjectClass(string $name): void
|
public function addChildObjectClass(string $name): void
|
||||||
{
|
{
|
||||||
if (! $this->child_objectclasses->contains($name))
|
if (! $this->child_objectclasses->has($name))
|
||||||
$this->child_objectclasses->push($name);
|
$this->child_objectclasses->push($name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,25 +90,6 @@ class HomeController extends Controller
|
|||||||
return $x->render();
|
return $x->render();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function entry_password_check(Request $request)
|
|
||||||
{
|
|
||||||
$dn = Crypt::decryptString($request->dn);
|
|
||||||
$o = config('server')->fetch($dn);
|
|
||||||
|
|
||||||
$password = $o->getObject('userpassword');
|
|
||||||
|
|
||||||
$result = collect();
|
|
||||||
foreach ($password as $key => $value) {
|
|
||||||
$type = $password->hash_id($value);
|
|
||||||
$compare = Arr::get($request->password,$key);
|
|
||||||
//Log::debug(sprintf('comparing [%s] with [%s] type [%s]',$value,$compare,$type));
|
|
||||||
|
|
||||||
$result->push((($compare !== NULL) && Attribute\Password::hash($type)->compare($value,$compare)) ? 'OK' :'FAIL');
|
|
||||||
}
|
|
||||||
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show a confirmation to update a DN
|
* Show a confirmation to update a DN
|
||||||
*
|
*
|
||||||
@ -122,19 +103,9 @@ class HomeController extends Controller
|
|||||||
|
|
||||||
$o = config('server')->fetch($dn);
|
$o = config('server')->fetch($dn);
|
||||||
|
|
||||||
foreach ($request->except(['_token','dn','userpassword_hash','userpassword']) as $key => $value)
|
foreach ($request->except(['_token','dn']) as $key => $value)
|
||||||
$o->{$key} = array_filter($value);
|
$o->{$key} = array_filter($value);
|
||||||
|
|
||||||
// We need to process and encrypt the password
|
|
||||||
$passwords = [];
|
|
||||||
foreach ($request->userpassword as $key => $value) {
|
|
||||||
if ($value) {
|
|
||||||
$type = Arr::get($request->userpassword_hash,$key);
|
|
||||||
array_push($passwords,Attribute\Password::hash($type)->encode($value));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$o->userpassword = $passwords;
|
|
||||||
|
|
||||||
if (! $o->getDirty())
|
if (! $o->getDirty())
|
||||||
return back()
|
return back()
|
||||||
->withInput()
|
->withInput()
|
||||||
@ -162,7 +133,6 @@ class HomeController extends Controller
|
|||||||
foreach ($request->except(['_token','dn']) as $key => $value)
|
foreach ($request->except(['_token','dn']) as $key => $value)
|
||||||
$o->{$key} = array_filter($value);
|
$o->{$key} = array_filter($value);
|
||||||
|
|
||||||
dd($o->getDirty(),$o,$request->all());
|
|
||||||
if (! $dirty=$o->getDirty())
|
if (! $dirty=$o->getDirty())
|
||||||
return back()
|
return back()
|
||||||
->withInput()
|
->withInput()
|
||||||
|
@ -32,7 +32,7 @@ class Entry extends Model
|
|||||||
parent::discardChanges();
|
parent::discardChanges();
|
||||||
|
|
||||||
// If we are discharging changes, we need to reset our $objects;
|
// If we are discharging changes, we need to reset our $objects;
|
||||||
$this->objects = $this->getAttributesAsObjects();
|
$this->objects = $this->getAttributesAsObjects($this->attributes);
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
@ -45,26 +45,28 @@ class Entry extends Model
|
|||||||
*/
|
*/
|
||||||
public function getAttributes(): array
|
public function getAttributes(): array
|
||||||
{
|
{
|
||||||
return $this->objects
|
return $this->objects->map(function($item) { return $item->values->toArray(); })->toArray();
|
||||||
->map(fn($item)=>$item->values->toArray())
|
|
||||||
->toArray();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine if the new and old values for a given key are equivalent.
|
* Determine if the new and old values for a given key are equivalent.
|
||||||
*
|
|
||||||
* @todo This function barfs on language tags, eg: key = givenname;lang-ja
|
|
||||||
*/
|
*/
|
||||||
protected function originalIsEquivalent(string $key): bool
|
protected function originalIsEquivalent(string $key): bool
|
||||||
{
|
{
|
||||||
$key = $this->normalizeAttributeKey($key);
|
$key = $this->normalizeAttributeKey($key);
|
||||||
|
|
||||||
// @todo Silently ignore keys of language tags - we should work with them
|
if ((! array_key_exists($key, $this->original)) && (! $this->objects->has($key))) {
|
||||||
if (str_contains($key,';'))
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
return ((! array_key_exists($key,$this->original)) && (! $this->objects->has($key)))
|
$current = $this->attributes[$key];
|
||||||
|| (! $this->getObject($key)->isDirty());
|
$original = $this->objects->get($key)->values;
|
||||||
|
|
||||||
|
if ($current === $original) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ! $this->getObject($key)->isDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function query(bool $noattrs=false): Builder
|
public static function query(bool $noattrs=false): Builder
|
||||||
@ -118,7 +120,7 @@ class Entry extends Model
|
|||||||
|
|
||||||
// We only set our objects on DN entries (otherwise we might get into a recursion loop if this is the schema DN)
|
// We only set our objects on DN entries (otherwise we might get into a recursion loop if this is the schema DN)
|
||||||
if ($this->dn && (! in_array($this->dn,Arr::get($this->attributes,'subschemasubentry',[])))) {
|
if ($this->dn && (! in_array($this->dn,Arr::get($this->attributes,'subschemasubentry',[])))) {
|
||||||
$this->objects = $this->getAttributesAsObjects();
|
$this->objects = $this->getAttributesAsObjects($this->attributes);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
$this->objects = collect();
|
$this->objects = collect();
|
||||||
@ -132,8 +134,8 @@ class Entry extends Model
|
|||||||
/**
|
/**
|
||||||
* Return a key to use for sorting
|
* Return a key to use for sorting
|
||||||
*
|
*
|
||||||
* @return string
|
|
||||||
* @todo This should be the DN in reverse order
|
* @todo This should be the DN in reverse order
|
||||||
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getSortKeyAttribute(): string
|
public function getSortKeyAttribute(): string
|
||||||
{
|
{
|
||||||
@ -146,7 +148,7 @@ class Entry extends Model
|
|||||||
{
|
{
|
||||||
$key = $this->normalizeAttributeKey($key);
|
$key = $this->normalizeAttributeKey($key);
|
||||||
|
|
||||||
if (! config('server')->schema('attributetypes')->contains($key))
|
if (config('server')->schema('attributetypes')->has($key) === FALSE)
|
||||||
throw new AttributeException('Schema doesnt have attribute [%s]',$key);
|
throw new AttributeException('Schema doesnt have attribute [%s]',$key);
|
||||||
|
|
||||||
if ($x=$this->objects->get($key)) {
|
if ($x=$this->objects->get($key)) {
|
||||||
@ -163,11 +165,11 @@ class Entry extends Model
|
|||||||
* @param array $attributes
|
* @param array $attributes
|
||||||
* @return Collection
|
* @return Collection
|
||||||
*/
|
*/
|
||||||
public function getAttributesAsObjects(): Collection
|
protected function getAttributesAsObjects(array $attributes): Collection
|
||||||
{
|
{
|
||||||
$result = collect();
|
$result = collect();
|
||||||
|
|
||||||
foreach ($this->attributes as $attribute => $value) {
|
foreach ($attributes as $attribute => $value) {
|
||||||
// If the attribute name has language tags
|
// If the attribute name has language 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)) {
|
||||||
@ -197,10 +199,10 @@ class Entry extends Model
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$sort = collect(config('ldap.attr_display_order',[]))->map(fn($item)=>strtolower($item));
|
$sort = collect(config('ldap.attr_display_order',[]))->transform(function($item) { return strtolower($item); });
|
||||||
|
|
||||||
// Order the attributes
|
// Order the attributes
|
||||||
return $result->sortBy([function(Attribute $a,Attribute $b) use ($sort): int {
|
$result = $result->sortBy([function(Attribute $a,Attribute $b) use ($sort): int {
|
||||||
if ($a === $b)
|
if ($a === $b)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -223,7 +225,9 @@ class Entry extends Model
|
|||||||
// Case where at least one attribute or its friendly name is in $attrs_display_order
|
// Case where at least one attribute or its friendly name is in $attrs_display_order
|
||||||
// return -1 if $a before $b in $attrs_display_order
|
// return -1 if $a before $b in $attrs_display_order
|
||||||
return ($a_key < $b_key) ? -1 : 1;
|
return ($a_key < $b_key) ? -1 : 1;
|
||||||
}]);
|
} ]);
|
||||||
|
|
||||||
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -257,8 +261,9 @@ class Entry extends Model
|
|||||||
*/
|
*/
|
||||||
public function getInternalAttributes(): Collection
|
public function getInternalAttributes(): Collection
|
||||||
{
|
{
|
||||||
return $this->objects
|
return $this->objects->filter(function($item) {
|
||||||
->filter(fn($item)=>$item->is_internal);
|
return $item->is_internal;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -269,15 +274,14 @@ class Entry extends Model
|
|||||||
*/
|
*/
|
||||||
public function getObject(string $key): Attribute|null
|
public function getObject(string $key): Attribute|null
|
||||||
{
|
{
|
||||||
return $this->objects
|
return $this->objects->get($this->normalizeAttributeKey($key));
|
||||||
->get($this->normalizeAttributeKey($key));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getObjects(): Collection
|
public function getObjects(): Collection
|
||||||
{
|
{
|
||||||
// In case we havent built our objects yet (because they werent available while determining the schema DN)
|
// In case we havent built our objects yet (because they werent available while determining the schema DN)
|
||||||
if ((! $this->objects->count()) && $this->attributes)
|
if ((! $this->objects->count()) && $this->attributes)
|
||||||
$this->objects = $this->getAttributesAsObjects();
|
$this->objects = $this->getAttributesAsObjects($this->attributes);
|
||||||
|
|
||||||
return $this->objects;
|
return $this->objects;
|
||||||
}
|
}
|
||||||
@ -289,8 +293,7 @@ class Entry extends Model
|
|||||||
*/
|
*/
|
||||||
public function getMissingAttributes(): Collection
|
public function getMissingAttributes(): Collection
|
||||||
{
|
{
|
||||||
return $this->getAvailableAttributes()
|
return $this->getAvailableAttributes()->diff($this->getVisibleAttributes());
|
||||||
->diff($this->getVisibleAttributes());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -300,14 +303,14 @@ class Entry extends Model
|
|||||||
*/
|
*/
|
||||||
public function getVisibleAttributes(): Collection
|
public function getVisibleAttributes(): Collection
|
||||||
{
|
{
|
||||||
return $this->objects
|
return $this->objects->filter(function($item) {
|
||||||
->filter(fn($item)=>! $item->is_internal);
|
return ! $item->is_internal;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public function hasAttribute(int|string $key): bool
|
public function hasAttribute(int|string $key): bool
|
||||||
{
|
{
|
||||||
return $this->objects
|
return $this->objects->has($key);
|
||||||
->has($key);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -11,6 +11,9 @@ trait MD5Updates
|
|||||||
{
|
{
|
||||||
public function isDirty(): bool
|
public function isDirty(): bool
|
||||||
{
|
{
|
||||||
|
if (! parent::isDirty())
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
foreach ($this->values->diff($this->oldValues) as $key => $value)
|
foreach ($this->values->diff($this->oldValues) as $key => $value)
|
||||||
if (md5(Arr::get($this->oldValues,$key)) !== $value)
|
if (md5(Arr::get($this->oldValues,$key)) !== $value)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -8,22 +8,22 @@ use App\Classes\LDAP\Attribute as LDAPAttribute;
|
|||||||
|
|
||||||
class Attribute extends Component
|
class Attribute extends Component
|
||||||
{
|
{
|
||||||
public ?LDAPAttribute $o;
|
public LDAPAttribute $o;
|
||||||
public bool $edit;
|
public bool $edit;
|
||||||
public bool $new;
|
public bool $new;
|
||||||
public bool $old;
|
public bool $old;
|
||||||
public ?string $na;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new component instance.
|
* Create a new component instance.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function __construct(?LDAPAttribute $o,bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,string $na=NULL)
|
public function __construct(LDAPAttribute $o,bool $edit,bool $old=FALSE,bool $new=FALSE)
|
||||||
{
|
{
|
||||||
$this->o = $o;
|
$this->o = $o;
|
||||||
$this->edit = $edit;
|
$this->edit = $edit;
|
||||||
$this->old = $old;
|
$this->old = $old;
|
||||||
$this->new = $new;
|
$this->new = $new;
|
||||||
$this->na = $na;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -33,9 +33,6 @@ class Attribute extends Component
|
|||||||
*/
|
*/
|
||||||
public function render()
|
public function render()
|
||||||
{
|
{
|
||||||
return $this->o
|
return $this->o->render($this->edit,$this->old,$this->new);
|
||||||
? $this->o
|
|
||||||
->render($this->edit,$this->old,$this->new)
|
|
||||||
: $this->na;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -153,25 +153,13 @@ return [
|
|||||||
'mail' => [
|
'mail' => [
|
||||||
'mail'=>[
|
'mail'=>[
|
||||||
'sometimes',
|
'sometimes',
|
||||||
'array',
|
'array','min:1'
|
||||||
'min:1'
|
|
||||||
],
|
],
|
||||||
'mail.*' => [
|
'mail.*' => [
|
||||||
'nullable',
|
'nullable',
|
||||||
'email'
|
'email'
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
'userpassword' => [
|
|
||||||
'userpassword' => [
|
|
||||||
'sometimes',
|
|
||||||
'array',
|
|
||||||
'min:1'
|
|
||||||
],
|
|
||||||
'userpassword.*' => [
|
|
||||||
'nullable',
|
|
||||||
'min:8'
|
|
||||||
]
|
|
||||||
],
|
|
||||||
'uidnumber' => [
|
'uidnumber' => [
|
||||||
'uidnumber' => [
|
'uidnumber' => [
|
||||||
'sometimes',
|
'sometimes',
|
||||||
|
12
package-lock.json
generated
12
package-lock.json
generated
@ -20,8 +20,7 @@
|
|||||||
"resolve-url-loader": "^5.0.0",
|
"resolve-url-loader": "^5.0.0",
|
||||||
"sass": "^1.58.3",
|
"sass": "^1.58.3",
|
||||||
"sass-loader": "^13.2.0",
|
"sass-loader": "^13.2.0",
|
||||||
"select2": "^4.1.0-rc.0",
|
"select2": "^4.1.0-rc.0"
|
||||||
"select2-bootstrap-5-theme": "^1.3.0"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@ampproject/remapping": {
|
"node_modules/@ampproject/remapping": {
|
||||||
@ -7645,15 +7644,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/select2/-/select2-4.1.0-rc.0.tgz",
|
"resolved": "https://registry.npmjs.org/select2/-/select2-4.1.0-rc.0.tgz",
|
||||||
"integrity": "sha512-Hr9TdhyHCZUtwznEH2CBf7967mEM0idtJ5nMtjvk3Up5tPukOLXbHUNmh10oRfeNIhj+3GD3niu+g6sVK+gK0A=="
|
"integrity": "sha512-Hr9TdhyHCZUtwznEH2CBf7967mEM0idtJ5nMtjvk3Up5tPukOLXbHUNmh10oRfeNIhj+3GD3niu+g6sVK+gK0A=="
|
||||||
},
|
},
|
||||||
"node_modules/select2-bootstrap-5-theme": {
|
|
||||||
"version": "1.3.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/select2-bootstrap-5-theme/-/select2-bootstrap-5-theme-1.3.0.tgz",
|
|
||||||
"integrity": "sha512-uEJDruP4tmwyKcs3V0oP7CIsyC45PGF5ddo8unwTp8OucJ1PSuTOBr+xbWaHTQPGnvp7N96psVQ5UBMQvFCcHA==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"bootstrap": "^5.1.3"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/selfsigned": {
|
"node_modules/selfsigned": {
|
||||||
"version": "2.4.1",
|
"version": "2.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz",
|
||||||
|
@ -25,7 +25,6 @@
|
|||||||
"resolve-url-loader": "^5.0.0",
|
"resolve-url-loader": "^5.0.0",
|
||||||
"sass": "^1.58.3",
|
"sass": "^1.58.3",
|
||||||
"sass-loader": "^13.2.0",
|
"sass-loader": "^13.2.0",
|
||||||
"select2": "^4.1.0-rc.0",
|
"select2": "^4.1.0-rc.0"
|
||||||
"select2-bootstrap-5-theme": "^1.3.0"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
10
public/css/custom.css
vendored
10
public/css/custom.css
vendored
@ -3,13 +3,3 @@ img.jpegphoto {
|
|||||||
max-width:100px;
|
max-width:100px;
|
||||||
height:100px;
|
height:100px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** ensure our userpassword has select is next to the password input */
|
|
||||||
div#userpassword .select2-container--bootstrap-5 .select2-selection {
|
|
||||||
font-size: inherit;
|
|
||||||
border-bottom-right-radius: unset;
|
|
||||||
border-top-right-radius: unset;
|
|
||||||
width: 7em;
|
|
||||||
border: #444054 1px solid;
|
|
||||||
background-color: #f0f0f0;
|
|
||||||
}
|
|
22
public/css/fixes.css
vendored
22
public/css/fixes.css
vendored
@ -269,25 +269,3 @@ pre code .line::before {
|
|||||||
display: inline-block;
|
display: inline-block;
|
||||||
border-right: 1px solid rgba(0, 0, 0, .5);
|
border-right: 1px solid rgba(0, 0, 0, .5);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** select2 rendering fixes */
|
|
||||||
/* The opened input box */
|
|
||||||
.select2-container--bootstrap-5 .select2-dropdown .select2-search .select2-search__field {
|
|
||||||
line-height: 1.0;
|
|
||||||
border: 1px solid #aaa;
|
|
||||||
}
|
|
||||||
|
|
||||||
.select2-container--bootstrap-5 .select2-dropdown .select2-results__options .select2-results__option {
|
|
||||||
padding: 0.3rem 0.2rem 0.3rem 0.4rem;
|
|
||||||
font-size: 95%;
|
|
||||||
}
|
|
||||||
|
|
||||||
select2-container--bootstrap-5 .select2-selection--multiple .select2-selection__clear, .select2-container--bootstrap-5 .select2-selection--single .select2-selection__clear {
|
|
||||||
width: 0.5rem;
|
|
||||||
height: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.select2-container--bootstrap-5 .select2-selection--single .select2-selection__rendered .select2-selection__placeholder {
|
|
||||||
line-height: 1.0;
|
|
||||||
font-size: 90%;
|
|
||||||
}
|
|
1
resources/sass/app.scss
vendored
1
resources/sass/app.scss
vendored
@ -6,4 +6,3 @@
|
|||||||
|
|
||||||
// Select2
|
// Select2
|
||||||
@import "select2/dist/css/select2";
|
@import "select2/dist/css/select2";
|
||||||
@import "select2-bootstrap-5-theme/dist/select2-bootstrap-5-theme";
|
|
||||||
|
@ -11,7 +11,14 @@
|
|||||||
<div class="h-100 bg-animation">
|
<div class="h-100 bg-animation">
|
||||||
<div class="d-flex h-100 justify-content-center align-items-center">
|
<div class="d-flex h-100 justify-content-center align-items-center">
|
||||||
<div class="mx-auto app-login-box col-md-8">
|
<div class="mx-auto app-login-box col-md-8">
|
||||||
<x-file-note file="login-note.html"/>
|
@if(file_exists('login-note.html'))
|
||||||
|
<div class="mx-auto card text-white card-body bg-primary w-50">
|
||||||
|
<h5 class="text-white card-title"><i class="icon fa-2x fas fa-info pe-3"></i><span class="font-size-xlg">NOTE</span></h5>
|
||||||
|
<span class="w-100 pb-0">
|
||||||
|
{!! file_get_contents('login-note.html') !!}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
<div class="modal-dialog w-100 mx-auto">
|
<div class="modal-dialog w-100 mx-auto">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
|
|
||||||
<div tabindex="-1" role="menu" aria-hidden="true" class="dropdown-menu dropdown-menu-right">
|
<div tabindex="-1" role="menu" aria-hidden="true" class="dropdown-menu dropdown-menu-right">
|
||||||
<ul class="nav flex-column">
|
<ul class="nav flex-column">
|
||||||
@if ((isset($page_actions) && $page_actions->contains('edit')) || old())
|
@if ((isset($page_actions) && ($page_actions->search('edit') !== FALSE)) || old())
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<span class="nav-link pt-0 pb-1">
|
<span class="nav-link pt-0 pb-1">
|
||||||
<button id="entry-edit" class="p-2 m-0 border-0 btn-transition btn btn-outline-dark w-100 text-start">
|
<button id="entry-edit" class="p-2 m-0 border-0 btn-transition btn btn-outline-dark w-100 text-start">
|
||||||
@ -37,7 +37,7 @@
|
|||||||
</li>
|
</li>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
@if (isset($page_actions) && $page_actions->contains('export'))
|
@if (isset($page_actions) && ($page_actions->search('export') !== FALSE))
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link pt-0 pb-1">
|
<a class="nav-link pt-0 pb-1">
|
||||||
<button type="button" class="p-2 m-0 border-0 btn-transition btn btn-outline-dark w-100 text-start" data-bs-toggle="modal" data-bs-target="#entry-export-modal" {{--data-bs-whatever="ldif"--}}>
|
<button type="button" class="p-2 m-0 border-0 btn-transition btn btn-outline-dark w-100 text-start" data-bs-toggle="modal" data-bs-target="#entry-export-modal" {{--data-bs-whatever="ldif"--}}>
|
||||||
@ -47,7 +47,7 @@
|
|||||||
</li>
|
</li>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
@if (isset($page_actions) && $page_actions->contains('copy'))
|
@if (isset($page_actions) && ($page_actions->search('copy') !== FALSE))
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link pt-0 pb-1">
|
<a class="nav-link pt-0 pb-1">
|
||||||
<button class="p-2 m-0 border-0 btn-transition btn btn-outline-dark w-100 text-start">
|
<button class="p-2 m-0 border-0 btn-transition btn btn-outline-dark w-100 text-start">
|
||||||
|
@ -33,8 +33,6 @@
|
|||||||
<link rel="stylesheet" href="{{ asset('/css/custom.css') }}">
|
<link rel="stylesheet" href="{{ asset('/css/custom.css') }}">
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
<!-- Page Styles -->
|
|
||||||
@yield('page-styles')
|
|
||||||
{{--
|
{{--
|
||||||
@if(file_exists('css/print.css'))
|
@if(file_exists('css/print.css'))
|
||||||
<!-- Printing Modifications -->
|
<!-- Printing Modifications -->
|
||||||
|
@ -15,6 +15,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<x-attribute :o="$o" :edit="true" :new="$new ?? FALSE"/>
|
<x-attribute :o="$o" :edit="true" :new="$new"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
@ -1,9 +1,9 @@
|
|||||||
<!-- $o=Attribute::class -->
|
<!-- $o=Attribute::class -->
|
||||||
<x-attribute.layout :edit="$edit ?? FALSE" :new="$new ?? FALSE" :o="$o">
|
<x-attribute.layout :edit="$edit" :new="$new" :o="$o">
|
||||||
@foreach(old($o->name_lc,($new ?? FALSE) ? [NULL] : $o->values) as $value)
|
@foreach (old($o->name_lc,$new ? [NULL] : $o->values) as $value)
|
||||||
@if (($edit ?? FALSE) && ! $o->is_rdn)
|
@if ($edit && ! $o->is_rdn)
|
||||||
<div class="input-group has-validation">
|
<div class="input-group has-validation">
|
||||||
<input type="text" @class(['form-control','is-invalid'=>($e=$errors->get($o->name_lc.'.'.$loop->index)),'mb-1','border-focus'=>($o->values->contains($value))]) name="{{ $o->name_lc }}[]" value="{{ $value }}" placeholder="{{ ! is_null($x=Arr::get($o->values,$loop->index)) ? $x : '['.__('NEW').']' }}" @readonly(! ($new ?? FALSE))>
|
<input type="text" class="form-control @if($e=$errors->get($o->name_lc.'.'.$loop->index))is-invalid @endif mb-1 @if($o->values->search($value) === FALSE) border-focus @endif" name="{{ $o->name_lc }}[]" value="{{ $value }}" placeholder="{{ ! is_null($x=Arr::get($o->values,$loop->index)) ? $x : '['.__('NEW').']' }}" @if (! $new)readonly="true" @endif">
|
||||||
|
|
||||||
<div class="invalid-feedback pb-2">
|
<div class="invalid-feedback pb-2">
|
||||||
@if($e)
|
@if($e)
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
@default
|
@default
|
||||||
<td>
|
<td>
|
||||||
<input type="hidden" name="{{ $o->name_lc }}[]" value="{{ md5($value) }}">
|
<input type="hidden" name="{{ $o->name_lc }}[]" value="{{ md5($value) }}">
|
||||||
<img @class(['jpegphoto','is-invalid'=>($e=$errors->get($o->name_lc.'.'.$loop->index))]) src="data:{{ $x }};base64, {{ base64_encode($value) }}" />
|
<img class="jpegphoto @if($e=$errors->get($o->name_lc.'.'.$loop->index))is-invalid @endif" src="data:{{ $x }};base64, {{ base64_encode($value) }}" />
|
||||||
|
|
||||||
@if ($edit)
|
@if ($edit)
|
||||||
<br>
|
<br>
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
<div class="row pt-2">
|
<div class="row pt-2">
|
||||||
<div @class(['col-1','d-none'=>(! $edit)])></div>
|
<div class="col-1 @if(! $edit)d-none @endif"></div>
|
||||||
<div class="col-10 p-2">
|
<div class="col-10 p-2">
|
||||||
<div id="{{ $o->name_lc }}">
|
<div id="{{ $o->name_lc }}">
|
||||||
{{ $slot }}
|
{{ $slot }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<x-attribute.widget.options :o="$o" :edit="$edit" :new="$new"/>
|
<x-attribute.widget.options :o="$o" :edit="$edit" :new="$new"></x-attribute.widget.options>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
@foreach (old($o->name_lc,$o->values) as $value)
|
@foreach (old($o->name_lc,$o->values) as $value)
|
||||||
@if ($edit && ($value === NULL || (! $o->isStructural($value))))
|
@if ($edit && ($value === NULL || (! $o->isStructural($value))))
|
||||||
<div class="input-group has-validation">
|
<div class="input-group has-validation">
|
||||||
<input type="text" @class(['form-control','is-invalid'=>($e=$errors->get($o->name_lc.'.'.$loop->index)),'mb-1','border-focus'=>$o->values->contains($value)]) name="{{ $o->name_lc }}[]" value="{{ $value }}" placeholder="{{ ! is_null($x=Arr::get($o->values,$loop->index)) ? $x : '['.__('NEW').']' }}" @readonly(true)>
|
<input type="text" class="form-control @if($e=$errors->get($o->name_lc.'.'.$loop->index))is-invalid @endif mb-1 @if($o->values->search($value) === FALSE) border-focus @endif" name="{{ $o->name_lc }}[]" value="{{ $value }}" placeholder="{{ ! is_null($x=Arr::get($o->values,$loop->index)) ? $x : '['.__('NEW').']' }}" readonly="true">
|
||||||
<div class="invalid-feedback pb-2">
|
<div class="invalid-feedback pb-2">
|
||||||
@if($e)
|
@if($e)
|
||||||
{{ join('|',$e) }}
|
{{ join('|',$e) }}
|
||||||
@ -14,7 +14,7 @@
|
|||||||
{{ $value }}
|
{{ $value }}
|
||||||
@if ($o->isStructural($value))
|
@if ($o->isStructural($value))
|
||||||
<input type="hidden" name="{{ $o->name_lc }}[]" value="{{ $value }}">
|
<input type="hidden" name="{{ $o->name_lc }}[]" value="{{ $value }}">
|
||||||
<span class="float-end">@lang('structural')</span>
|
<span class="float-end mb-2">@lang('structural')</span>
|
||||||
@endif
|
@endif
|
||||||
<br>
|
<br>
|
||||||
@endif
|
@endif
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
|
<!-- @todo We are not handling redirect backs with updated values -->
|
||||||
<!-- $o=Password::class -->
|
<!-- $o=Password::class -->
|
||||||
<x-attribute.layout :edit="$edit ?? FALSE" :new="$new ?? FALSE" :o="$o">
|
<x-attribute.layout :edit="$edit" :new="$new" :o="$o">
|
||||||
@foreach($o->values as $value)
|
@foreach ($o->values as $value)
|
||||||
@if($edit)
|
@if ($edit)
|
||||||
<div class="input-group has-validation mb-3">
|
<div class="input-group has-validation">
|
||||||
<x-form.select class="password" id="userpassword_hash_{{$loop->index}}" name="userpassword_hash[]" :value="$o->hash_id($value)" :options="$helpers" allowclear="false" disabled="true"/>
|
<input type="password" class="form-control @if($e=$errors->get($o->name_lc.'.'.$loop->index))is-invalid @endif mb-1 @if($o->values->search($value) === FALSE) border-focus @endif" 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)>
|
|
||||||
|
|
||||||
<div class="invalid-feedback pb-2">
|
<div class="invalid-feedback pb-2">
|
||||||
@if($e)
|
@if($e)
|
||||||
@ -13,17 +13,11 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@else
|
@else
|
||||||
{{ (($x=$o->hash_id($value)) && ($x !== 'Clear')) ? sprintf('{%s}',$x) : '' }}{{ str_repeat('x',8) }}
|
{{ $value }}<br>
|
||||||
@endif
|
@endif
|
||||||
@endforeach
|
@endforeach
|
||||||
</x-attribute.layout>
|
|
||||||
|
|
||||||
@if($edit)
|
<span class="p-0 m-0">
|
||||||
<div class="row">
|
<span class="btn btn-sm btn-outline-dark mt-3"><i class="fas fa-user-check"></i> @lang('Check Password')</span>
|
||||||
<div class="offset-1 col-4 p-2">
|
</span>
|
||||||
<span class="p-0 m-0">
|
</x-attribute.layout>
|
||||||
<button type="button" class="btn btn-transition btn-sm btn-outline-dark mt-3" data-bs-toggle="modal" data-bs-target="#userpassword-check-modal"><i class="fas fa-user-check"></i> @lang('Check Password')</button>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@endif
|
|
@ -2,12 +2,24 @@
|
|||||||
<span class="btn btn-sm btn-outline-focus mt-3"><i class="fas fa-fw fa-exchange"></i> @lang('Rename')</span>
|
<span class="btn btn-sm btn-outline-focus mt-3"><i class="fas fa-fw fa-exchange"></i> @lang('Rename')</span>
|
||||||
@elseif($edit && $o->can_addvalues)
|
@elseif($edit && $o->can_addvalues)
|
||||||
<span class="p-0 m-0">
|
<span class="p-0 m-0">
|
||||||
<span @class(['btn','btn-sm','btn-outline-primary','mt-3','addable','d-none'=>(! $new)]) id="{{ $o->name_lc }}"><i class="fas fa-fw fa-plus"></i> @lang('Add Value')</span>
|
<span class="btn btn-sm btn-outline-primary mt-3 addable @if(! $new)d-none @endif" id="{{ $o->name_lc }}"><i class="fas fa-fw fa-plus"></i> @lang('Add Value')</span>
|
||||||
|
@if($new)
|
||||||
|
<script type="text/javascript">
|
||||||
|
$(document).ready(function() {
|
||||||
|
// Create a new entry when Add Value clicked
|
||||||
|
$('#{{ $o->name_lc }}.addable').click(function (item) {
|
||||||
|
var cln = $(this).parent().parent().find('input:last').clone();
|
||||||
|
cln.val('').attr('placeholder', '[@lang('NEW')]');
|
||||||
|
cln.appendTo('#' + item.currentTarget.id)
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
@endif
|
||||||
</span>
|
</span>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
@section('page-scripts')
|
@section('page-scripts')
|
||||||
@if($edit && $o->can_addvalues)
|
@if(($edit && $o->can_addvalues))
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
// Create a new entry when Add Value clicked
|
// Create a new entry when Add Value clicked
|
||||||
|
@ -1,11 +0,0 @@
|
|||||||
@if($errors->any())
|
|
||||||
<div class="alert alert-danger">
|
|
||||||
<h4 class="alert-heading"><i class="fas fa-fw fa-thumbs-down"></i> Error?</h4>
|
|
||||||
<hr>
|
|
||||||
<ul style="list-style-type: square;">
|
|
||||||
@foreach ($errors->all() as $error)
|
|
||||||
<li>{{ $error }}</li>
|
|
||||||
@endforeach
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
@endif
|
|
@ -1,12 +0,0 @@
|
|||||||
@if(file_exists($file))
|
|
||||||
<div class="row pb-3">
|
|
||||||
<div class="col-12">
|
|
||||||
<div class="mx-auto card text-white card-body bg-primary w-50">
|
|
||||||
<h5 class="text-white card-title"><i class="icon fa-2x fas fa-info pe-3"></i><span class="font-size-xlg">NOTE</span></h5>
|
|
||||||
<span class="w-100 pb-0">
|
|
||||||
{!! file_get_contents($file) !!}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@endif
|
|
@ -1,29 +0,0 @@
|
|||||||
<div class="form-group">
|
|
||||||
@if(isset($label))
|
|
||||||
<label {{ $attributes->only(['class'])->merge(['class'=>'form-label']) }} for="{{ $id ?? $name }}">{!! html_entity_decode($label) !!}</label>
|
|
||||||
@endisset
|
|
||||||
<div class="input-group has-validation">
|
|
||||||
@if(isset($icon) || isset($prepend))
|
|
||||||
{{-- // messes with the icon box, we have rounded corners on the right side
|
|
||||||
<div class="input-group-prepend">
|
|
||||||
--}}
|
|
||||||
<span class="input-group-text">@isset($icon)<i class="bi {{ $icon }}"></i>@endisset @isset($prepend){!! $prepend !!}@endisset</span>
|
|
||||||
{{--
|
|
||||||
</div>
|
|
||||||
--}}
|
|
||||||
@endif
|
|
||||||
{{ $slot }}
|
|
||||||
@isset($name)
|
|
||||||
<span class="invalid-feedback">
|
|
||||||
@error((! empty($old)) ? $old : $name)
|
|
||||||
{{ $message }}
|
|
||||||
@elseif(isset($feedback))
|
|
||||||
{{ $feedback }}
|
|
||||||
@enderror
|
|
||||||
</span>
|
|
||||||
@endisset
|
|
||||||
</div>
|
|
||||||
@isset($helper)
|
|
||||||
<span class="input-helper">{!! html_entity_decode($helper) !!}</span>
|
|
||||||
@endif
|
|
||||||
</div>
|
|
@ -1,9 +0,0 @@
|
|||||||
<button type="cancel" id="cancel" {{ $attributes->class(['btn','btn-sm','btn-outline-dark']) }}>Cancel</button>
|
|
||||||
|
|
||||||
@section('page-scripts')
|
|
||||||
<script type="text/javascript">
|
|
||||||
$(document).ready(function() {
|
|
||||||
$('#cancel').on('click',()=>history.back());
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
@append
|
|
@ -1,9 +0,0 @@
|
|||||||
<button id="form-reset" class="btn btn-outline-danger">@lang('Reset')</button>
|
|
||||||
|
|
||||||
@section('page-scripts')
|
|
||||||
<script>
|
|
||||||
$(document).ready(function() {
|
|
||||||
$('#form-reset').on('click',()=>$('#{{$form}}')[0].reset());
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
@append
|
|
@ -1,63 +0,0 @@
|
|||||||
<x-form.base {{ $attributes }}>
|
|
||||||
@isset($name)
|
|
||||||
<input type="hidden" id="{{ $name }}_disabled" name="{{ $name }}" value="" disabled>
|
|
||||||
@endisset
|
|
||||||
<select style="width: 80%" class="form-select @isset($name)@error((! empty($old)) ? $old : $name) is-invalid @enderror @endisset" id="{{ $id ?? $name }}" @isset($name)name="{{ $name }}"@endisset @required(isset($required) && $required) @disabled(isset($disabled) && $disabled)>
|
|
||||||
@if(empty($value) || isset($addnew) || isset($choose))
|
|
||||||
<option value=""></option>
|
|
||||||
@isset($addnew)
|
|
||||||
<option value="new">{{ $addnew ?: 'Add New' }}</option>
|
|
||||||
@endisset
|
|
||||||
@endif
|
|
||||||
|
|
||||||
@isset($options)
|
|
||||||
@empty($groupby)
|
|
||||||
@foreach($options as $option)
|
|
||||||
@continue(! Arr::get($option,'value'))
|
|
||||||
<option value="{{ Arr::get($option,'id') }}" @selected(isset($name) && (Arr::get($option,'id') == old($old ?? $name,$value ?? '')))>{{ Arr::get($option,'value') }}</option>
|
|
||||||
@endforeach
|
|
||||||
|
|
||||||
@else
|
|
||||||
@foreach($options->groupBy($groupby) as $group)
|
|
||||||
<optgroup label="{{ $groupby == 'active' ? (Arr::get($group->first(),$groupby) ? 'Active' : 'Not Active') : Arr::get($group->first(),$groupby) }}">
|
|
||||||
@foreach($group as $option)
|
|
||||||
@continue(! Arr::get($option,'value'))
|
|
||||||
<option value="{{ Arr::get($option,'id') }}" @selected(isset($name) && (Arr::get($option,'id') == old($old ?? $name,$value ?? '')))>{{ Arr::get($option,'value') }}</option>
|
|
||||||
@endforeach
|
|
||||||
</optgroup>
|
|
||||||
@endforeach
|
|
||||||
@endempty
|
|
||||||
@endisset
|
|
||||||
</select>
|
|
||||||
</x-form.base>
|
|
||||||
|
|
||||||
@section('page-scripts')
|
|
||||||
<script type="text/javascript">
|
|
||||||
// Select doesnt support read only so we'll use disable and a new field
|
|
||||||
@isset($name)
|
|
||||||
function {{$id ?? $name}}_readonly(on) {
|
|
||||||
if (on) {
|
|
||||||
$('#{{ $name }}').prop('disabled',true);
|
|
||||||
$('#{{ $name }}_disabled').prop('disabled',false).val($('#{{ $name }}').val());
|
|
||||||
|
|
||||||
} else {
|
|
||||||
$('#{{ $name }}').prop('disabled',false);
|
|
||||||
$('#{{ $name }}_disabled').prop('disabled',true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@endisset
|
|
||||||
|
|
||||||
$(document).ready(function() {
|
|
||||||
$('#{{ $id ?? $name }}').select2({
|
|
||||||
theme: 'bootstrap-5',
|
|
||||||
dropdownAutoWidth: true,
|
|
||||||
width: 'style',
|
|
||||||
allowClear: {{ $allowclear ?? 'true' }},
|
|
||||||
placeholder: '{{ $placeholder ?? '' }}',
|
|
||||||
@isset($addvalues)
|
|
||||||
tags: true,
|
|
||||||
@endisset
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
@append
|
|
@ -1,9 +0,0 @@
|
|||||||
<button id="form-submit" class="btn btn-sm btn-success">@lang($action)</button>
|
|
||||||
|
|
||||||
@section('page-scripts')
|
|
||||||
<script type="text/javascript">
|
|
||||||
$(document).ready(function() {
|
|
||||||
$('#form-submit').on('click',()=>$('#{{$form}}')[0].submit());
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
@append
|
|
@ -1,7 +0,0 @@
|
|||||||
@if(session()->has('note'))
|
|
||||||
<div class="alert alert-info">
|
|
||||||
<h4 class="alert-heading"><i class="fas fa-fw fa-note-sticky"></i> Note:</h4>
|
|
||||||
<hr>
|
|
||||||
<p>{{ session()->pull('note') }}</p>
|
|
||||||
</div>
|
|
||||||
@endif
|
|
@ -1,12 +0,0 @@
|
|||||||
@if(session()->has('success'))
|
|
||||||
<div class="alert alert-success">
|
|
||||||
<h4 class="alert-heading"><i class="fas fa-fw fa-thumbs-up"></i> Success!</h4>
|
|
||||||
<hr>
|
|
||||||
<p>{{ session()->pull('success') }}</p>
|
|
||||||
<ul style="list-style-type: square;">
|
|
||||||
@foreach (session()->pull('updated') as $key => $values)
|
|
||||||
<li>{{ $key }}: {{ join(',',$values) }}</li>
|
|
||||||
@endforeach
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
@endif
|
|
@ -1,32 +0,0 @@
|
|||||||
<table class="table table-borderless">
|
|
||||||
<tr>
|
|
||||||
<td class="{{ ($x=$o->getObject('jpegphoto')) ? 'border' : '' }}" rowspan="2">
|
|
||||||
{!! $x ? $x->render(FALSE,TRUE) : sprintf('<div class="page-title-icon f32"><i class="%s"></i></div>',$o->icon() ?? "fas fa-info") !!}
|
|
||||||
</td>
|
|
||||||
<td class="text-end align-text-top p-0 {{ $x ? 'ps-5' : 'pt-2' }}"><strong>{{ $dn }}</strong></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="line-height-1" style="font-size: 55%;vertical-align: bottom;" colspan="2">
|
|
||||||
<table>
|
|
||||||
<tr>
|
|
||||||
<td class="p-1 m-1">Created</td>
|
|
||||||
<th class="p-1 m-1">
|
|
||||||
<x-attribute :o="$o->getObject('createtimestamp')" :na="__('Unknown')"/> [<x-attribute :o="$o->getObject('creatorsname')" :na="__('Unknown')"/>]
|
|
||||||
</th>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="p-1 m-1">Modified</td>
|
|
||||||
<th class="p-1 m-1">
|
|
||||||
<x-attribute :o="$o->getObject('modifytimestamp')" :na="__('Unknown')"/> [<x-attribute :o="$o->getObject('modifiersname')" :na="__('Unknown')"/>]
|
|
||||||
</th>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="p-1 m-1">UUID</td>
|
|
||||||
<th class="p-1 m-1">
|
|
||||||
<x-attribute :o="$o->getObject('entryuuid')" :na="__('Unknown')"/>
|
|
||||||
</th>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
@ -1,15 +1,66 @@
|
|||||||
@extends('layouts.dn')
|
@extends('layouts.dn')
|
||||||
|
|
||||||
@section('page_title')
|
@section('page_title')
|
||||||
@include('fragment.dn.header')
|
<table class="table table-borderless">
|
||||||
|
<tr>
|
||||||
|
<td class="{{ ($x=$o->getObject('jpegphoto')) ? 'border' : '' }}" rowspan="2">{!! $x ? $x->render() : sprintf('<div class="page-title-icon f32"><i class="%s"></i></div>',$o->icon() ?? "fas fa-info") !!}</td>
|
||||||
|
<td class="text-end align-text-top p-0 {{ $x ? 'ps-5' : 'pt-2' }}"><strong>{{ $dn }}</strong></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="line-height-1" style="font-size: 55%;vertical-align: bottom;" colspan="2">
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td class="p-1 m-1">Created</td>
|
||||||
|
<th class="p-1 m-1">{{ ($x=$o->getObject('createtimestamp')) ? $x->render() : __('Unknown') }} [{{ ($x=$o->getObject('creatorsname')) ? $x->render() : __('Unknown') }}]</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="p-1 m-1">Modified</td>
|
||||||
|
<th class="p-1 m-1">{{ ($x=$o->getObject('modifytimestamp')) ? $x->render() : __('Unknown') }} [{{ ($x=$o->getObject('modifiersname')) ? $x->render() : __('Unknown') }}]</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="p-1 m-1">UUID</td>
|
||||||
|
<th class="p-1 m-1">{{ $o->entryuuid[0] ?? '' }}</th>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
@endsection
|
@endsection
|
||||||
|
|
||||||
@section('main-content')
|
@section('main-content')
|
||||||
<x-note/>
|
@if(session()->has('note'))
|
||||||
<x-success/>
|
<div class="alert alert-info">
|
||||||
<x-error/>
|
<h4 class="alert-heading"><i class="fas fa-fw fa-note-sticky"></i> Note:</h4>
|
||||||
|
<hr>
|
||||||
|
<p>{{ session()->pull('note') }}</p>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
@if(session()->has('success'))
|
||||||
|
<div class="alert alert-success">
|
||||||
|
<h4 class="alert-heading"><i class="fas fa-fw fa-thumbs-up"></i> Success!</h4>
|
||||||
|
<hr>
|
||||||
|
<p>{{ session()->pull('success') }}</p>
|
||||||
|
<ul style="list-style-type: square;">
|
||||||
|
@foreach (session()->pull('updated') as $key => $values)
|
||||||
|
<li>{{ $key }}: {{ join(',',$values) }}</li>
|
||||||
|
@endforeach
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
<!-- @todo If we are redirected here, check old() and add back any attributes that were in the original submission -->
|
<!-- @todo If we are redirected here, check old() and add back any attributes that were in the original submission -->
|
||||||
|
@if($errors->any())
|
||||||
|
<div class="alert alert-danger">
|
||||||
|
<h4 class="alert-heading"><i class="fas fa-fw fa-thumbs-down"></i> Error?</h4>
|
||||||
|
<hr>
|
||||||
|
<ul style="list-style-type: square;">
|
||||||
|
@foreach ($errors->all() as $error)
|
||||||
|
<li>{{ $error }}</li>
|
||||||
|
@endforeach
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
<div class="main-card mb-3 card">
|
<div class="main-card mb-3 card">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
@ -51,7 +102,13 @@
|
|||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12 pt-2">
|
<div class="col-12 pt-2">
|
||||||
<x-form.select id="newattr" label="Select from..." :options="$o->getMissingAttributes()->sortBy('name')->map(fn($item)=>['id'=>$item->name,'value'=>$item->name_lc])"/>
|
<label for="newattr" class="form-label">Select from...</label>
|
||||||
|
<select class="form-select" id="newattr">
|
||||||
|
<option value=""> </option>
|
||||||
|
@foreach ($o->getMissingAttributes() as $ao)
|
||||||
|
<option value="{{ $ao->name_lc }}">{{ $ao->name }}</option>
|
||||||
|
@endforeach
|
||||||
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
@ -59,14 +116,14 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-2"></div>
|
<div class="col-2"></div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
|
||||||
|
|
||||||
<div class="row d-none pt-3">
|
<div class="row d-none pt-3">
|
||||||
<div class="col-12 offset-sm-2 col-sm-4 col-lg-2">
|
<div class="col-12 offset-sm-2 col-sm-4 col-lg-2">
|
||||||
<x-form.reset form="dn-edit"/>
|
<span id="form-reset" class="btn btn-outline-danger">@lang('Reset')</span>
|
||||||
<x-form.submit action="Update" form="dn-edit"/>
|
<span id="form-submit" class="btn btn-success">@lang('Update')</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Internal Attributes -->
|
<!-- Internal Attributes -->
|
||||||
@ -112,7 +169,7 @@
|
|||||||
@endsection
|
@endsection
|
||||||
|
|
||||||
@section('page-modals')
|
@section('page-modals')
|
||||||
<!-- EXPORT -->
|
<!-- Modal -->
|
||||||
<div class="modal fade" id="entry-export-modal" tabindex="-1" aria-labelledby="entry-export-label" aria-hidden="true">
|
<div class="modal fade" id="entry-export-modal" tabindex="-1" aria-labelledby="entry-export-label" aria-hidden="true">
|
||||||
<div class="modal-dialog modal-lg modal-fullscreen-xl-down">
|
<div class="modal-dialog modal-lg modal-fullscreen-xl-down">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
@ -127,47 +184,11 @@
|
|||||||
|
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="button" class="btn btn-secondary btn-sm" data-bs-dismiss="modal">Close</button>
|
<button type="button" class="btn btn-secondary btn-sm" data-bs-dismiss="modal">Close</button>
|
||||||
<button type="button" class="btn btn-primary btn-sm" id="entry-export-download">Download</button>
|
<button id="entry-export-download" type="button" class="btn btn-primary btn-sm">Download</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@if($up=$o->getObject('userpassword'))
|
|
||||||
<!-- CHECK USERPASSWORD -->
|
|
||||||
<div class="modal fade" id="userpassword-check-modal" tabindex="-1" aria-labelledby="userpassword-check-label" aria-hidden="true">
|
|
||||||
<div class="modal-dialog modal-md modal-fullscreen-md-down">
|
|
||||||
<div class="modal-content">
|
|
||||||
<div class="modal-header">
|
|
||||||
<h1 class="modal-title fs-5" id="userpassword-check-label">Check Passwords for {{ $dn }}</h1>
|
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="modal-body">
|
|
||||||
<table class="table table-bordered p-1">
|
|
||||||
@foreach($up->values as $key => $value)
|
|
||||||
<tr>
|
|
||||||
<th>Check</th>
|
|
||||||
<td>{{ (($xx=$up->hash_id($value)) && ($xx !== 'Clear')) ? sprintf('{%s}',$xx) : '' }}{{ str_repeat('x',8) }}</td>
|
|
||||||
<td>
|
|
||||||
<input type="password" style="width: 90%" name="password[{{$key}}]"> <i class="fas fa-fw fa-lock"></i>
|
|
||||||
<div class="invalid-feedback pb-2">
|
|
||||||
Invalid Password
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
@endforeach
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="modal-footer">
|
|
||||||
<button type="button" class="btn btn-secondary btn-sm" data-bs-dismiss="modal">Close</button>
|
|
||||||
<button type="button" class="btn btn-primary btn-sm" id="userpassword_check_submit"><i class="fas fa-fw fa-spinner fa-spin d-none"></i> Check</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@endif
|
|
||||||
@endsection
|
@endsection
|
||||||
|
|
||||||
@section('page-scripts')
|
@section('page-scripts')
|
||||||
@ -192,11 +213,6 @@
|
|||||||
$(this).attr('readonly',false);
|
$(this).attr('readonly',false);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Our password type
|
|
||||||
$('div#userpassword .form-select').each(function() {
|
|
||||||
$(this).prop('disabled',false);
|
|
||||||
})
|
|
||||||
|
|
||||||
$('.row.d-none').removeClass('d-none');
|
$('.row.d-none').removeClass('d-none');
|
||||||
$('.addable.d-none').removeClass('d-none');
|
$('.addable.d-none').removeClass('d-none');
|
||||||
$('.deletable.d-none').removeClass('d-none');
|
$('.deletable.d-none').removeClass('d-none');
|
||||||
@ -207,6 +223,14 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
|
$('#form-reset').click(function() {
|
||||||
|
$('#dn-edit')[0].reset();
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#form-submit').click(function() {
|
||||||
|
$('#dn-edit')[0].submit();
|
||||||
|
});
|
||||||
|
|
||||||
$('#newattr').on('change',function(item) {
|
$('#newattr').on('change',function(item) {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: 'GET',
|
type: 'GET',
|
||||||
@ -246,9 +270,10 @@
|
|||||||
download('ldap-export.ldif',ldif.html());
|
download('ldap-export.ldif',ldif.html());
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#entry-export-modal').on('shown.bs.modal',function() {
|
$('#entry-export-modal').on('shown.bs.modal', function () {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: 'GET',
|
type: 'GET',
|
||||||
|
beforeSend: function() {},
|
||||||
success: function(data) {
|
success: function(data) {
|
||||||
$('#entry-export').empty().append(data);
|
$('#entry-export').empty().append(data);
|
||||||
},
|
},
|
||||||
@ -261,65 +286,6 @@
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@if($up)
|
|
||||||
$('button[id=userpassword_check_submit]').on('click',function(item) {
|
|
||||||
var that = $(this);
|
|
||||||
|
|
||||||
var passwords = $('#userpassword-check-modal')
|
|
||||||
.find('input[name^="password["')
|
|
||||||
.map((key,item)=>item.value);
|
|
||||||
|
|
||||||
if (passwords.length === 0) return false;
|
|
||||||
|
|
||||||
$.ajax({
|
|
||||||
type: 'POST',
|
|
||||||
beforeSend: function() {
|
|
||||||
// Disable submit, add spinning icon
|
|
||||||
that.prop('disabled',true);
|
|
||||||
that.find('i').removeClass('d-none');
|
|
||||||
},
|
|
||||||
complete: function() {
|
|
||||||
that.prop('disabled',false);
|
|
||||||
that.find('i').addClass('d-none');
|
|
||||||
},
|
|
||||||
success: function(data) {
|
|
||||||
data.forEach(function(item,key) {
|
|
||||||
var i = $('#userpassword-check-modal')
|
|
||||||
.find('input[name="password['+key+']')
|
|
||||||
.siblings('i');
|
|
||||||
|
|
||||||
var feedback = $('#userpassword-check-modal')
|
|
||||||
.find('input[name="password['+key+']')
|
|
||||||
.siblings('div.invalid-feedback');
|
|
||||||
|
|
||||||
console.log(feedback.attr('display'));
|
|
||||||
|
|
||||||
if (item === 'OK') {
|
|
||||||
i.removeClass('text-danger').addClass('text-success').removeClass('fa-lock').addClass('fa-lock-open');
|
|
||||||
if (feedback.is(':visible'))
|
|
||||||
feedback.hide();
|
|
||||||
} else {
|
|
||||||
i.removeClass('text-success').addClass('text-danger').removeClass('fa-lock-open').addClass('fa-lock');
|
|
||||||
if (! feedback.is(':visible'))
|
|
||||||
feedback.show();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
error: function(e) {
|
|
||||||
if (e.status != 412)
|
|
||||||
alert('That didnt work? Please try again....');
|
|
||||||
},
|
|
||||||
url: '{{ url('entry/password/check') }}',
|
|
||||||
data: {
|
|
||||||
dn: '{{ $o->getDNSecure() }}',
|
|
||||||
password: Array.from(passwords),
|
|
||||||
},
|
|
||||||
dataType: 'json',
|
|
||||||
cache: false
|
|
||||||
})
|
|
||||||
});
|
|
||||||
@endif
|
|
||||||
|
|
||||||
@if(old())
|
@if(old())
|
||||||
editmode();
|
editmode();
|
||||||
@endif
|
@endif
|
||||||
|
@ -52,13 +52,13 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
|
||||||
|
|
||||||
<div class="card-footer">
|
<div class="card-footer">
|
||||||
<span class="ms-auto">
|
<span class="ms-auto">
|
||||||
<x-form.submit action="Process" form="import-form"/>
|
<button type="submit" class="btn btn-success btn-sm">Process</button>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
--}}
|
--}}
|
||||||
|
|
||||||
@section('main-content')
|
@section('main-content')
|
||||||
<div class="card card-solid mb-3">
|
<div class="card card-solid">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12 col-sm-4">
|
<div class="col-12 col-sm-4">
|
||||||
@ -38,7 +38,19 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<x-file-note file="home-note.html"/>
|
@if(file_exists('home-note.html'))
|
||||||
|
<hr>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12 offset-lg-2 col-lg-8">
|
||||||
|
<div class="mx-auto card text-white card-body bg-primary">
|
||||||
|
<h5 class="text-white card-title"><i class="icon fa-2x fas fa-info pe-3"></i><span class="font-size-xlg">NOTE</span></h5>
|
||||||
|
<span class="w-100 pb-0">
|
||||||
|
{!! file_get_contents('home-note.html') !!}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
@endsection
|
@endsection
|
||||||
|
|
||||||
@section('page-scripts')
|
@section('page-scripts')
|
||||||
|
@ -12,4 +12,3 @@
|
|||||||
|
|
||||||
@yield('page-modals')
|
@yield('page-modals')
|
||||||
@yield('page-scripts')
|
@yield('page-scripts')
|
||||||
@yield('page-styles')
|
|
@ -1,25 +1,83 @@
|
|||||||
@extends('home')
|
@extends('home')
|
||||||
|
|
||||||
@section('page_title')
|
@section('page_title')
|
||||||
@include('fragment.dn.header')
|
<table class="table table-borderless">
|
||||||
|
<tr>
|
||||||
|
<td class="{{ ($x=$o->getObject('jpegphoto')) ? 'border' : '' }}" rowspan="2">
|
||||||
|
{!! $x ? $x->render(FALSE,TRUE) : sprintf('<div class="page-title-icon f32"><i class="%s"></i></div>',$o->icon() ?? "fas fa-info") !!}
|
||||||
|
</td>
|
||||||
|
<td class="text-end align-text-top p-0 {{ $x ? 'ps-5' : 'pt-2' }}"><strong>{{ $dn }}</strong></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="line-height-1" style="font-size: 55%;vertical-align: bottom;" colspan="2">
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td class="p-1 m-1">Created</td>
|
||||||
|
<th class="p-1 m-1">
|
||||||
|
{{ ($x=$o->getObject('createtimestamp')) ? $x->render() : __('Unknown') }} [{{ ($x=$o->getObject('creatorsname')) ? $x->render() : __('Unknown') }}]
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="p-1 m-1">Modified</td>
|
||||||
|
<th class="p-1 m-1">
|
||||||
|
{{ ($x=$o->getObject('modifytimestamp')) ? $x->render() : __('Unknown') }} [{{ ($x=$o->getObject('modifiersname')) ? $x->render() : __('Unknown') }}]
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="p-1 m-1">UUID</td>
|
||||||
|
<th class="p-1 m-1">{{ $o->entryuuid[0] ?? '' }}</th>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
@endsection
|
@endsection
|
||||||
|
|
||||||
@section('main-content')
|
@section('main-content')
|
||||||
<x-note/>
|
@if(session()->has('note'))
|
||||||
<x-success/>
|
<div class="alert alert-info">
|
||||||
<x-error/>
|
<h4 class="alert-heading"><i class="fas fa-fw fa-note-sticky"></i> Note:</h4>
|
||||||
|
<hr>
|
||||||
|
<p>{{ session()->pull('note') }}</p>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
@if(session()->has('success'))
|
||||||
|
<div class="alert alert-success">
|
||||||
|
<h4 class="alert-heading"><i class="fas fa-fw fa-thumbs-up"></i> Success!</h4>
|
||||||
|
<hr>
|
||||||
|
<p>{{ session()->pull('success') }}</p>
|
||||||
|
<ul style="list-style-type: square;">
|
||||||
|
@foreach (session()->pull('updated') as $key => $values)
|
||||||
|
<li>{{ $key }}: {{ join(',',$values) }}</li>
|
||||||
|
@endforeach
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
@if($errors->any())
|
||||||
|
<div class="alert alert-danger">
|
||||||
|
<h4 class="alert-heading"><i class="fas fa-fw fa-thumbs-down"></i> Error?</h4>
|
||||||
|
<hr>
|
||||||
|
<ul style="list-style-type: square;">
|
||||||
|
@foreach ($errors->all() as $error)
|
||||||
|
<li>{{ $error }}</li>
|
||||||
|
@endforeach
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
<div class="main-card mb-3 card">
|
<div class="main-card mb-3 card">
|
||||||
<form id="dn-update" method="POST" class="needs-validation" action="{{ url('entry/update/commit') }}" novalidate>
|
<form id="dn-update" method="POST" class="needs-validation" action="{{ url('entry/update/commit') }}" novalidate>
|
||||||
@csrf
|
@csrf
|
||||||
<input type="hidden" name="dn" value="{{ $o->getDNSecure() }}">
|
|
||||||
|
|
||||||
|
<input type="hidden" name="dn" value="{{ $o->getDNSecure() }}">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12 col-lg-6 mx-auto pt-3">
|
<div class="col-12 col-lg-6 col-xl-4 mx-auto pt-3">
|
||||||
|
|
||||||
<div class="card-title"><h3>@lang('Do you want to make the following changes?')</h3></div>
|
<div class="card-title"><h3>@lang('Do you want to make the following changes?')</h3></div>
|
||||||
<table class="table table-bordered table-striped w-100">
|
<table class="table table-bordered table-striped">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Attribute</th>
|
<th>Attribute</th>
|
||||||
@ -29,18 +87,16 @@
|
|||||||
</thead>
|
</thead>
|
||||||
|
|
||||||
<tbody>
|
<tbody>
|
||||||
@foreach ($o->getAttributesAsObjects()->filter(fn($item)=>$item->isDirty()) as $key => $oo)
|
@foreach ($o->getDirty() as $key => $value)
|
||||||
<tr>
|
<tr>
|
||||||
<th rowspan="{{ $x=max($oo->values->keys()->max(),$oo->old_values->keys()->max())+1}}">
|
<th rowspan="{{ $x=max(count($value),count(Arr::get($o->getOriginal(),$key,[])))}}">{{ $key }}</th>
|
||||||
<abbr title="{{ $oo->description }}">{{ $oo->name }}</abbr>
|
|
||||||
</th>
|
|
||||||
@for($xx=0;$xx<$x;$xx++)
|
@for($xx=0;$xx<$x;$xx++)
|
||||||
@if($xx)
|
@if($xx)
|
||||||
</tr><tr>
|
</tr><tr>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
<td>{{ $oo->render_item_old($xx) ?: '['.strtoupper(__('New Value')).']' }}</td>
|
<td>{{ Arr::get(Arr::get($o->getOriginal(),$key),$xx,'['.strtoupper(__('New Value')).']') }}</td>
|
||||||
<td>{{ $oo->render_item_new($xx) ?: '['.strtoupper(__('Deleted')).']' }}<input type="hidden" name="{{ $key }}[]" value="{{ Arr::get($oo->values,$xx) }}"></td>
|
<td>{{ ($y=Arr::get($value,$xx)) ?: '['.strtoupper(__('Deleted')).']' }}<input type="hidden" name="{{ $key }}[]" value="{{ $y }}"></td>
|
||||||
@endfor
|
@endfor
|
||||||
</tr>
|
</tr>
|
||||||
@endforeach
|
@endforeach
|
||||||
@ -48,15 +104,28 @@
|
|||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="row pt-3">
|
||||||
|
<div class="col-12 offset-sm-2 col-sm-4 col-lg-2 mx-auto">
|
||||||
|
<span id="form-reset" class="btn btn-outline-danger">@lang('Reset')</span>
|
||||||
|
<span id="form-submit" class="btn btn-success">@lang('Update')</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<div class="row p-3">
|
|
||||||
<div class="col-12 offset-sm-2 col-sm-4 col-lg-2 mx-auto">
|
|
||||||
<x-form.cancel/>
|
|
||||||
<x-form.submit action="Update" form="dn-update"/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@endsection
|
@endsection
|
||||||
|
|
||||||
|
@section('page-scripts')
|
||||||
|
<script type="text/javascript">
|
||||||
|
$(document).ready(function() {
|
||||||
|
$('#form-reset').click(function() {
|
||||||
|
$('#dn-update')[0].reset();
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#form-submit').click(function() {
|
||||||
|
$('#dn-update')[0].submit();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
@append
|
@ -42,6 +42,5 @@ Route::post('entry/update/commit',[HomeController::class,'entry_update']);
|
|||||||
Route::post('entry/update/pending',[HomeController::class,'entry_pending_update']);
|
Route::post('entry/update/pending',[HomeController::class,'entry_pending_update']);
|
||||||
Route::get('entry/newattr/{id}',[HomeController::class,'entry_newattr']);
|
Route::get('entry/newattr/{id}',[HomeController::class,'entry_newattr']);
|
||||||
Route::get('entry/export/{id}',[HomeController::class,'entry_export']);
|
Route::get('entry/export/{id}',[HomeController::class,'entry_export']);
|
||||||
Route::post('entry/password/check/',[HomeController::class,'entry_password_check']);
|
|
||||||
|
|
||||||
Route::post('import/process/{type}',[HomeController::class,'import']);
|
Route::post('import/process/{type}',[HomeController::class,'import']);
|
Loading…
x
Reference in New Issue
Block a user