Compare commits

...

6 Commits

Author SHA1 Message Date
735b1c542f Fix rendering updated attributes on entries that trigger a template
All checks were successful
Create Docker Image / Test Application (x86_64) (push) Successful in 31s
Create Docker Image / Build Docker Image (x86_64) (push) Successful in 1m26s
Create Docker Image / Build Docker Image (arm64) (push) Successful in 2m47s
Create Docker Image / Final Docker Image Manifest (push) Successful in 9s
2025-06-21 23:37:09 +10:00
8e41f314a4 Framework and javascript dependancies update 2025-06-21 23:37:09 +10:00
d1a9ed69c3 Update README with v2.2 updates, as well as updating the home page 2025-06-21 23:37:09 +10:00
df3a6d30a5 Enable disabling internal templates, as well as having custom templates 2025-06-21 23:37:09 +10:00
d17d94a32b Change our internal template keys to be prefixed with an underscore for easier identification 2025-06-21 23:37:09 +10:00
7ce1695549 Working JS Template Engine with a basic functionality 2025-06-21 23:37:09 +10:00
24 changed files with 668 additions and 181 deletions

View File

@ -1,4 +1,10 @@
# phpLDAPadmin # phpLDAPadmin
![GitHub commit activity](https://img.shields.io/github/commit-activity/m/leenooks/phpldapadmin)
![Docker Pulls](https://img.shields.io/docker/pulls/phpldapadmin/phpldapadmin)
![GitHub Downloads (all assets, all releases)](https://img.shields.io/github/downloads/leenooks/phpldapadmin/total)
![GitHub Release Date](https://img.shields.io/github/release-date/leenooks/phpldapadmin)
![GitHub commits since latest release](https://img.shields.io/github/commits-since/leenooks/phpldapadmin/latest)
phpLDAPadmin is a web based LDAP data management tool for system administrators. It is commonly known and referred by many as "PLA". phpLDAPadmin is a web based LDAP data management tool for system administrators. It is commonly known and referred by many as "PLA".
PLA is designed to be compliant with LDAP RFCs, enabling it to be used with any LDAP server. PLA is designed to be compliant with LDAP RFCs, enabling it to be used with any LDAP server.
@ -27,38 +33,29 @@ Take a look at the [Docker Container](https://github.com/leenooks/phpLDAPadmin/w
> >
> Open an issue (details below) with enough information for me to be able to recreate the problem. An `LDIF` will be invaluable if it is not handling data correctly. > Open an issue (details below) with enough information for me to be able to recreate the problem. An `LDIF` will be invaluable if it is not handling data correctly.
## Version 2 Progress ## Templates
Starting with v2.2, PLA reintroduces the template engine. Each point release going forward will improve the template
functionality. Check [releases](releases) for details.
The update to v2 is progressing well - here is a list of work to do and done: Templates in v2 are in JSON format (in v1 they were XML format). If you want to create your own templates you can use
the [example.json](blob/master/templates/example.json) template as a guide. Place your custom templates in a subdirectory
under `templates`, eg: `templates/custom`, and they wont be overwritten by an update.
- [X] Creating new LDAP entries ## Outstanding items
- [X] Delete existing LDAP entries Compare to v1.x, there are a couple of outstanding items to address
- [X] Updating existing LDAP Entries
- [X] Password attributes Entry Editing:
- [X] Support different password hash options
- [X] Validate password is correct
- [ ] JpegPhoto Create/Delete - [ ] JpegPhoto Create/Delete
- [ ] Binary attribute upload - [ ] Binary attribute upload
- [X] JpegPhoto Display - [ ] If removing an objectClass, remove all attributes that only that objectclass provided
- [X] ObjectClass Add/Remove
- [X] Add additional required attributes (for ObjectClass Addition)
- [ ] Remove existing required attributes (for ObjectClass Removal)
- [X] Add additional values to Attributes that support multiple values
- [X] Delete extra values for Attributes that support multiple values
- [ ] Delete Attributes
- [ ] Templates to enable entries to conform to a custom standard
- [ ] Autopopulate attribute values
- [X] Login to LDAP server
- [X] Configure login by a specific attribute
- [X] Logout LDAP server
- [X] Export entries as an LDAP
- [X] Import LDIF
- [X] Schema Browser
- [X] Searching
- [ ] Enforcing attribute uniqueness
- [ ] Is there something missing?
Support is known for these LDAP servers: Templates Engine
- [ ] Present SELECT lists when an attribute is marked as `type=select`
- [ ] Enforcing attribute uniqueness
Raise a [feature request](issues/new) if there is a capability that you would like to see added to PLA.
## Support is known for these LDAP servers:
- [X] OpenLDAP - [X] OpenLDAP
- [X] OpenDJ - [X] OpenDJ
- [ ] Microsoft Active Directory - [ ] Microsoft Active Directory

View File

@ -3,19 +3,28 @@
namespace App\Classes; namespace App\Classes;
use Illuminate\Support\Arr; use Illuminate\Support\Arr;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage; use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str; use Illuminate\Support\Str;
class Template class Template
{ {
private string $file; private const LOGKEY = 'T--';
private(set) string $file;
private array $template; private array $template;
private(set) bool $invalid = FALSE; private(set) bool $invalid = FALSE;
private(set) string $reason = ''; private(set) string $reason = '';
private Collection $on_change_target;
private Collection $on_change_attribute;
private bool $on_change_processed = FALSE;
public function __construct(string $file) public function __construct(string $file)
{ {
$td = Storage::disk(config('pla.template.dir')); $td = Storage::disk(config('pla.template.dir'));
$this->on_change_attribute = collect();
$this->on_change_target = collect();
$this->file = $file; $this->file = $file;
@ -48,4 +57,175 @@ class Template
{ {
return array_key_exists($key,$this->template); return array_key_exists($key,$this->template);
} }
public function onChange(string $attribute): Collection|NULL
{
if (! $this->on_change_processed)
$this->onChangeProcessing();
return $this->on_change_attribute
->get(strtolower($attribute));
}
/**
* Is this attribute's value populated by any onChange processing rules
*
* @param string $attribute
* @return bool
*/
public function onChangeAttribute(string $attribute): bool
{
if (! $this->on_change_processed)
$this->onChangeProcessing();
return $this->on_change_attribute
->has(strtolower($attribute));
}
/**
* Return the onchange JavaScript for attribute
*
* @return Collection
*/
private function onChangeProcessing(): void
{
foreach (Arr::get($this->template,'attributes',[]) as $attribute => $detail) {
$result = collect();
foreach (Arr::get($detail,'onchange',[]) as $item) {
list($command,$args) = preg_split('/^=([a-zA-Z]+)\((.+)\)$/',$item,-1,PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY);
switch ($command) {
case 'autoFill':
$result->push($this->autofill($args));
break;
}
}
if ($result->count())
$this->on_change_attribute->put(strtolower($attribute),$result);
}
$this->on_change_processed = TRUE;
}
/**
* Is this attribute's value populated by any onChange processing rules
*
* @param string $attribute
* @return bool
*/
public function onChangeTarget(string $attribute): bool
{
if (! $this->on_change_processed)
$this->onChangeProcessing();
return $this->on_change_target
->has(strtolower($attribute));
}
/**
* autoFill - javascript to have one attribute fill the value of another
*
* args: is a literal string, with two parts, delimited by a semi-colon ;
* + The first part is the attribute that will be populated
* + The second part may contain many fields like %attr|start-end/flags|additionalcontrolchar%
* to substitute values read from other fields.
* + |start-end is optional, but must be present if the k flag is used
* + /flags is optional
* + |additionalcontrolchar is optional, and specific to a flag being used
*
* + flags may be:
* T:(?) Read display text from selection item (drop-down list), otherwise, read the value of the field
* For fields that aren't selection items, /T shouldn't be used, and the field value will always be read
* k:(?) Tokenize:
* If the "k" flag is not given:
* + A |start-end instruction will perform a sub-string operation upon the value of the attr, passing
* character positions start-end through
* + start can be 0 for first character, or any other integer
* + end can be 0 for last character, or any other integer for a specific position
* If the "k" flag is given:
* + The string read will be split into fields, using : as a delimiter
* + start indicates which field number to pass through
*
* If additionalcontrolchar is given, it will be used as delimiter (e.g. this allows for splitting
* e-mail addresses into domain and domain-local part)
* l: Make the result lower case
* U: Make the result upper case
* A:(?) Remap special characters to their corresponding ASCII value
*
* @note Attributes rendered on the page are lowercase, eg: <attribute id="gidnumber"> for gidNumber
* @note JavaScript generated here depends on js/template.js
* (?) = to test
*/
private function autofill(string $arg): string
{
if (! preg_match('/;/',$arg)) {
Log::alert(sprintf('%s:Invalid argument given to autofill [%s]',self::LOGKEY,$arg));
return '';
}
$result = '';
// $attr has our attribute to update, $string is the format to use when updating it
list($attr,$string) = preg_split('(([^,]+);(.*))',$arg,-1,PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
$this->on_change_target->put(strtolower($attr),$string);
$output = $string;
//$result .= sprintf("\n// %s\n",$arg);
$m = [];
// MATCH : 0 = highlevel match, 1 = attr, 2 = subst, 3 = mod, 4 = delimiter
preg_match_all('/%(\w+)(?:\|([0-9]*-[0-9])+)?(?:\/([klTUA]+))?(?:\|(.)?)?%/U',$string,$m);
foreach ($m[0] as $index => $null) {
$match_attr = strtolower($m[1][$index]);
$match_subst = $m[2][$index];
$match_mod = $m[3][$index];
$match_delim = $m[4][$index];
$substrarray = [];
$result .= sprintf("var %s;\n",$match_attr);
if (str_contains($match_mod,'k')) {
preg_match_all('/([0-9]+)/',trim($match_subst),$substrarray);
$delimiter = ($match_delim === '') ? ' ' : preg_quote($match_delim);
$result .= sprintf(" %s = %s.split('%s')[%s];\n",$match_attr,$match_attr,$delimiter,$substrarray[1][0] ?? '0');
} else {
// Work out the start and end chars needed from this value if we have a range specifier
preg_match_all('/([0-9]*)-([0-9]+)/',$match_subst,$substrarray);
if ((isset($substrarray[1][0]) && $substrarray[1][0]) || (isset($substrarray[2][0]) && $substrarray[2][0])) {
$result .= sprintf("%s = get_attribute('%s',%d,%s);\n",
$match_attr,$match_attr,
$substrarray[1][0] ?? '0',
$substrarray[2][0] ?: sprintf('%s.length',$match_attr));
} else {
$result .= sprintf("%s = get_attribute('%s');\n",$match_attr,$match_attr);
}
}
if (str_contains($match_mod,'l'))
$result .= sprintf("%s = %s.toLowerCase();\n",$match_attr,$match_attr);
if (str_contains($match_mod,'U'))
$result .= sprintf("%s = %s.toUpperCase();\n",$match_attr,$match_attr);
if (str_contains($match_mod,'A'))
$result .= sprintf("%s = toAscii(%s);\n",$match_attr,$match_attr);
// For debugging
//$result .= sprintf("console.log('%s will return:'+%s);\n",$match_attr,$match_attr);
// Reformat out output into JS variables
$output = preg_replace('/'.preg_quote($m[0][$index],'/').'/','\'+'.$match_attr.'+\'',$output);
}
$result .= sprintf("put_attribute('%s','%s');\n",strtolower($attr),$output);
$result .= "\n";
return $result;
}
} }

View File

@ -38,7 +38,7 @@ class AjaxController extends Controller
*/ */
public function children(Request $request): Collection public function children(Request $request): Collection
{ {
$dn = Crypt::decryptString($request->query('key')); $dn = Crypt::decryptString($request->query('_key'));
// Sometimes our key has a command, so we'll ignore it // Sometimes our key has a command, so we'll ignore it
if (str_starts_with($dn,'*') && ($x=strpos($dn,'|'))) if (str_starts_with($dn,'*') && ($x=strpos($dn,'|')))

View File

@ -28,6 +28,8 @@ class HomeController extends Controller
{ {
private const LOGKEY = 'CHc'; private const LOGKEY = 'CHc';
private const INTERNAL_POST = ['_key','_rdn','_rdn_value','_step','_template','_token','_userpassword_hash'];
/** /**
* Create a new object in the LDAP server * Create a new object in the LDAP server
* *
@ -37,7 +39,7 @@ class HomeController extends Controller
*/ */
public function entry_add(EntryAddRequest $request): \Illuminate\View\View 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);
$key = $this->request_key($request,collect(old())); $key = $this->request_key($request,collect(old()));
@ -46,18 +48,12 @@ class HomeController extends Controller
$o = new Entry; $o = new Entry;
$o->setRDNBase($key['dn']); $o->setRDNBase($key['dn']);
foreach (collect(old())->except(['_token','key','step','rdn','rdn_value','userpassword_hash']) as $old => $value) foreach (collect(old())->except(self::INTERNAL_POST) as $old => $value)
$o->{$old} = array_filter($value); $o->{$old} = array_filter($value);
if (count($x=collect(old('objectclass',$request->validated('objectclass')))->dot()->filter())) { if (old('_template',$request->validated('template'))) {
$o->objectclass = Arr::undot($x); $template = $o->template(old('_template',$request->validated('template')));
// Also add in our required attributes
foreach ($o->getAvailableAttributes()->filter(fn($item)=>$item->is_must) as $ao)
$o->{$ao->name} = [Entry::TAG_NOTAG=>''];
} elseif ($request->validated('template')) {
$template = $o->template($request->validated('template'));
$o->objectclass = [Entry::TAG_NOTAG=>$template->objectclasses->toArray()]; $o->objectclass = [Entry::TAG_NOTAG=>$template->objectclasses->toArray()];
foreach ($o->getAvailableAttributes() foreach ($o->getAvailableAttributes()
@ -66,9 +62,16 @@ class HomeController extends Controller
{ {
$o->{$ao->name} = [Entry::TAG_NOTAG=>'']; $o->{$ao->name} = [Entry::TAG_NOTAG=>''];
} }
} elseif (count($x=collect(old('objectclass',$request->validated('objectclass')))->dot()->filter())) {
$o->objectclass = Arr::undot($x);
// Also add in our required attributes
foreach ($o->getAvailableAttributes()->filter(fn($item)=>$item->is_must) as $ao)
$o->{$ao->name} = [Entry::TAG_NOTAG=>''];
} }
$step = $request->step ? $request->step+1 : old('step'); $step = $request->get('_step') ? $request->get('_step')+1 : old('_step');
return view('frame') return view('frame')
->with('subframe','create') ->with('subframe','create')
@ -104,6 +107,7 @@ class HomeController extends Controller
return $view return $view
->with('o',$o) ->with('o',$o)
->with('langtag',Entry::TAG_NOTAG) ->with('langtag',Entry::TAG_NOTAG)
->with('template',NULL)
->with('updated',FALSE); ->with('updated',FALSE);
} }
@ -111,12 +115,12 @@ class HomeController extends Controller
{ {
$key = $this->request_key($request,collect(old())); $key = $this->request_key($request,collect(old()));
$dn = sprintf('%s=%s,%s',$request->rdn,$request->rdn_value,$key['dn']); $dn = sprintf('%s=%s,%s',$request->get('_rdn'),$request->get('_rdn_value'),$key['dn']);
$o = new Entry; $o = new Entry;
$o->setDn($dn); $o->setDn($dn);
foreach ($request->except(['_token','key','step','rdn','rdn_value','userpassword_hash']) as $key => $value) foreach ($request->except(self::INTERNAL_POST) as $key => $value)
$o->{$key} = array_filter($value); $o->{$key} = array_filter($value);
try { try {
@ -212,7 +216,7 @@ class HomeController extends Controller
*/ */
public function entry_objectclass_add(Request $request): Collection public function entry_objectclass_add(Request $request): Collection
{ {
$dn = $request->key ? Crypt::decryptString($request->dn) : ''; $dn = $request->get('_key') ? Crypt::decryptString($request->dn) : '';
$oc = Factory::create($dn,'objectclass',$request->oc); $oc = Factory::create($dn,'objectclass',$request->oc);
$ocs = $oc $ocs = $oc
@ -267,7 +271,7 @@ 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','_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) // @todo Need to handle incoming attributes that were modified by MD5Updates Trait (eg: jpegphoto)
@ -284,7 +288,7 @@ class HomeController extends Controller
} }
if ($value) { if ($value) {
$type = Arr::get($request->userpassword_hash,$dotkey); $type = Arr::get($request->get('_userpassword_hash'),$dotkey);
$passwords[$dotkey] = Password::hash_id($type) $passwords[$dotkey] = Password::hash_id($type)
->encode($value); ->encode($value);
} }
@ -368,6 +372,7 @@ class HomeController extends Controller
* @param Request $request * @param Request $request
* @param Collection|null $old * @param Collection|null $old
* @return \Illuminate\View\View * @return \Illuminate\View\View
* @throws InvalidUsage
*/ */
public function frame(Request $request,?Collection $old=NULL): \Illuminate\View\View public function frame(Request $request,?Collection $old=NULL): \Illuminate\View\View
{ {
@ -390,7 +395,7 @@ class HomeController extends Controller
// @todo Need to handle if DN is null, for example if the user's session expired and the ACLs dont let them retrieve $key['dn'] // @todo Need to handle if DN is null, for example if the user's session expired and the ACLs dont let them retrieve $key['dn']
$o = config('server')->fetch($key['dn']); $o = config('server')->fetch($key['dn']);
foreach (collect(old())->except(['key','dn','step','_token','userpassword_hash','rdn','rdn_value']) as $attr => $value) foreach (collect(old())->except(array_merge(self::INTERNAL_POST,['dn'])) as $attr => $value)
$o->{$attr} = $value; $o->{$attr} = $value;
} }
@ -478,8 +483,8 @@ class HomeController extends Controller
// Setup // Setup
$cmd = NULL; $cmd = NULL;
$dn = NULL; $dn = NULL;
$key = $request->get('key',old('key')) $key = $request->get('_key',old('_key'))
? Crypt::decryptString($request->get('key',old('key'))) ? Crypt::decryptString($request->get('_key',old('_key')))
: NULL; : NULL;
// Determine if our key has a command // Determine if our key has a command
@ -491,9 +496,9 @@ class HomeController extends Controller
$dn = ($m[2] !== '_NOP') ? $m[2] : NULL; $dn = ($m[2] !== '_NOP') ? $m[2] : NULL;
} }
} elseif (old('dn',$request->get('key'))) { } elseif (old('dn',$request->get('_key'))) {
$cmd = 'dn'; $cmd = 'dn';
$dn = Crypt::decryptString(old('dn',$request->get('key'))); $dn = Crypt::decryptString(old('dn',$request->get('_key')));
} }
return ['cmd'=>$cmd,'dn'=>$dn]; return ['cmd'=>$cmd,'dn'=>$dn];
@ -510,12 +515,12 @@ class HomeController extends Controller
public function schema_frame(Request $request): \Illuminate\View\View 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->get('_key') && (! config('server')->schema($request->type)->has($request->get('_key'))))
abort(404); abort(404);
return view('frames.schema') return view('frames.schema')
->with('type',$request->type) ->with('type',$request->type)
->with('key',$request->key); ->with('key',$request->get('_key'));
} }
/** /**

View File

@ -17,8 +17,8 @@ class EntryAddRequest extends FormRequest
public function messages(): array public function messages(): array
{ {
return [ return [
'rdn' => __('RDN is required.'), '_rdn' => __('RDN is required.'),
'rdn_value' => __('RDN value is required.'), '_rdn_value' => __('RDN value is required.'),
]; ];
} }
@ -51,7 +51,7 @@ class EntryAddRequest extends FormRequest
->filter() ->filter()
->flatMap(fn($item)=>$item) ->flatMap(fn($item)=>$item)
->merge([ ->merge([
'key' => [ '_key' => [
'required', 'required',
new DNExists, new DNExists,
function (string $attribute,mixed $value,\Closure $fail) { function (string $attribute,mixed $value,\Closure $fail) {
@ -66,9 +66,9 @@ class EntryAddRequest extends FormRequest
} }
}, },
], ],
'rdn' => 'required_if:step,2|string|min:1', '_rdn' => 'required_if:_step,2|string|min:1',
'rdn_value' => 'required_if:step,2|string|min:1', '_rdn_value' => 'required_if:_step,2|string|min:1',
'step' => 'int|min:1|max:2', '_step' => 'int|min:1|max:2',
'objectclass'=>[ 'objectclass'=>[
'required', 'required',
'array', 'array',
@ -81,7 +81,7 @@ class EntryAddRequest extends FormRequest
// If this is step 1 and there is no objectclass, and no template, then fail // If this is step 1 and there is no objectclass, and no template, then fail
if ((! $oc->count()) if ((! $oc->count())
&& (request()->post('step') == 1) && (request()->post('_step') == 1)
&& (! request()->post('template'))) && (! request()->post('template')))
{ {
$fail(__('Select an objectclass or a template')); $fail(__('Select an objectclass or a template'));
@ -101,7 +101,7 @@ class EntryAddRequest extends FormRequest
// If this is step 1 and there is no objectclass, and no template, then fail // If this is step 1 and there is no objectclass, and no template, then fail
if ((! collect($value)->filter()->count()) if ((! collect($value)->filter()->count())
&& (request()->post('step') == 1) && (request()->post('_step') == 1)
&& (! $oc->count())) && (! $oc->count()))
{ {
$fail(__('Select an objectclass or a template')); $fail(__('Select an objectclass or a template'));

View File

@ -53,7 +53,10 @@ class Entry extends Model
$template_dir = Storage::disk(config('pla.template.dir')); $template_dir = Storage::disk(config('pla.template.dir'));
$templates = collect(); $templates = collect();
foreach (array_filter($template_dir->files(),fn($item)=>Str::endsWith($item,'.json')) as $file) { foreach (array_filter($template_dir->files('.',TRUE),fn($item)=>Str::endsWith($item,'.json')) as $file) {
if (config('pla.template.exclude_system',FALSE) && Str::doesntContain($file,'/'))
continue;
$to = new Template($file); $to = new Template($file);
if ($to->invalid) { if ($to->invalid) {

165
composer.lock generated
View File

@ -8,16 +8,16 @@
"packages": [ "packages": [
{ {
"name": "brick/math", "name": "brick/math",
"version": "0.12.3", "version": "0.13.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/brick/math.git", "url": "https://github.com/brick/math.git",
"reference": "866551da34e9a618e64a819ee1e01c20d8a588ba" "reference": "fc7ed316430118cc7836bf45faff18d5dfc8de04"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/brick/math/zipball/866551da34e9a618e64a819ee1e01c20d8a588ba", "url": "https://api.github.com/repos/brick/math/zipball/fc7ed316430118cc7836bf45faff18d5dfc8de04",
"reference": "866551da34e9a618e64a819ee1e01c20d8a588ba", "reference": "fc7ed316430118cc7836bf45faff18d5dfc8de04",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -56,7 +56,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/brick/math/issues", "issues": "https://github.com/brick/math/issues",
"source": "https://github.com/brick/math/tree/0.12.3" "source": "https://github.com/brick/math/tree/0.13.1"
}, },
"funding": [ "funding": [
{ {
@ -64,7 +64,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2025-02-28T13:11:00+00:00" "time": "2025-03-29T13:50:30+00:00"
}, },
{ {
"name": "carbonphp/carbon-doctrine-types", "name": "carbonphp/carbon-doctrine-types",
@ -288,16 +288,16 @@
}, },
{ {
"name": "directorytree/ldaprecord-laravel", "name": "directorytree/ldaprecord-laravel",
"version": "v3.4.1", "version": "v3.4.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/DirectoryTree/LdapRecord-Laravel.git", "url": "https://github.com/DirectoryTree/LdapRecord-Laravel.git",
"reference": "15f56e01319852d41023633d3688ac4aa139aa6e" "reference": "28c5a7aa42aa3fa631f9c0f0c8236fd19bc7b00c"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/DirectoryTree/LdapRecord-Laravel/zipball/15f56e01319852d41023633d3688ac4aa139aa6e", "url": "https://api.github.com/repos/DirectoryTree/LdapRecord-Laravel/zipball/28c5a7aa42aa3fa631f9c0f0c8236fd19bc7b00c",
"reference": "15f56e01319852d41023633d3688ac4aa139aa6e", "reference": "28c5a7aa42aa3fa631f9c0f0c8236fd19bc7b00c",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -343,7 +343,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/DirectoryTree/LdapRecord-Laravel/issues", "issues": "https://github.com/DirectoryTree/LdapRecord-Laravel/issues",
"source": "https://github.com/DirectoryTree/LdapRecord-Laravel/tree/v3.4.1" "source": "https://github.com/DirectoryTree/LdapRecord-Laravel/tree/v3.4.2"
}, },
"funding": [ "funding": [
{ {
@ -351,7 +351,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2025-03-21T19:16:44+00:00" "time": "2025-06-13T15:46:25+00:00"
}, },
{ {
"name": "doctrine/inflector", "name": "doctrine/inflector",
@ -1199,20 +1199,20 @@
}, },
{ {
"name": "laravel/framework", "name": "laravel/framework",
"version": "v12.16.0", "version": "v12.19.3",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/laravel/framework.git", "url": "https://github.com/laravel/framework.git",
"reference": "293bb1c70224faebfd3d4328e201c37115da055f" "reference": "4e6ec689ef704bb4bd282f29d9dd658dfb4fb262"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/laravel/framework/zipball/293bb1c70224faebfd3d4328e201c37115da055f", "url": "https://api.github.com/repos/laravel/framework/zipball/4e6ec689ef704bb4bd282f29d9dd658dfb4fb262",
"reference": "293bb1c70224faebfd3d4328e201c37115da055f", "reference": "4e6ec689ef704bb4bd282f29d9dd658dfb4fb262",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"brick/math": "^0.11|^0.12", "brick/math": "^0.11|^0.12|^0.13",
"composer-runtime-api": "^2.2", "composer-runtime-api": "^2.2",
"doctrine/inflector": "^2.0.5", "doctrine/inflector": "^2.0.5",
"dragonmantank/cron-expression": "^3.4", "dragonmantank/cron-expression": "^3.4",
@ -1410,7 +1410,7 @@
"issues": "https://github.com/laravel/framework/issues", "issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework" "source": "https://github.com/laravel/framework"
}, },
"time": "2025-05-27T15:49:44+00:00" "time": "2025-06-18T12:56:23+00:00"
}, },
{ {
"name": "laravel/prompts", "name": "laravel/prompts",
@ -2315,16 +2315,16 @@
}, },
{ {
"name": "nesbot/carbon", "name": "nesbot/carbon",
"version": "3.9.1", "version": "3.10.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/CarbonPHP/carbon.git", "url": "https://github.com/CarbonPHP/carbon.git",
"reference": "ced71f79398ece168e24f7f7710462f462310d4d" "reference": "c1397390dd0a7e0f11660f0ae20f753d88c1f3d9"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/ced71f79398ece168e24f7f7710462f462310d4d", "url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/c1397390dd0a7e0f11660f0ae20f753d88c1f3d9",
"reference": "ced71f79398ece168e24f7f7710462f462310d4d", "reference": "c1397390dd0a7e0f11660f0ae20f753d88c1f3d9",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -2332,7 +2332,7 @@
"ext-json": "*", "ext-json": "*",
"php": "^8.1", "php": "^8.1",
"psr/clock": "^1.0", "psr/clock": "^1.0",
"symfony/clock": "^6.3 || ^7.0", "symfony/clock": "^6.3.12 || ^7.0",
"symfony/polyfill-mbstring": "^1.0", "symfony/polyfill-mbstring": "^1.0",
"symfony/translation": "^4.4.18 || ^5.2.1 || ^6.0 || ^7.0" "symfony/translation": "^4.4.18 || ^5.2.1 || ^6.0 || ^7.0"
}, },
@ -2342,14 +2342,13 @@
"require-dev": { "require-dev": {
"doctrine/dbal": "^3.6.3 || ^4.0", "doctrine/dbal": "^3.6.3 || ^4.0",
"doctrine/orm": "^2.15.2 || ^3.0", "doctrine/orm": "^2.15.2 || ^3.0",
"friendsofphp/php-cs-fixer": "^3.57.2", "friendsofphp/php-cs-fixer": "^3.75.0",
"kylekatarnls/multi-tester": "^2.5.3", "kylekatarnls/multi-tester": "^2.5.3",
"ondrejmirtes/better-reflection": "^6.25.0.4",
"phpmd/phpmd": "^2.15.0", "phpmd/phpmd": "^2.15.0",
"phpstan/extension-installer": "^1.3.1", "phpstan/extension-installer": "^1.4.3",
"phpstan/phpstan": "^1.11.2", "phpstan/phpstan": "^2.1.17",
"phpunit/phpunit": "^10.5.20", "phpunit/phpunit": "^10.5.46",
"squizlabs/php_codesniffer": "^3.9.0" "squizlabs/php_codesniffer": "^3.13.0"
}, },
"bin": [ "bin": [
"bin/carbon" "bin/carbon"
@ -2417,7 +2416,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2025-05-01T19:51:51+00:00" "time": "2025-06-12T10:24:28+00:00"
}, },
{ {
"name": "nette/schema", "name": "nette/schema",
@ -2483,16 +2482,16 @@
}, },
{ {
"name": "nette/utils", "name": "nette/utils",
"version": "v4.0.6", "version": "v4.0.7",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/nette/utils.git", "url": "https://github.com/nette/utils.git",
"reference": "ce708655043c7050eb050df361c5e313cf708309" "reference": "e67c4061eb40b9c113b218214e42cb5a0dda28f2"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/nette/utils/zipball/ce708655043c7050eb050df361c5e313cf708309", "url": "https://api.github.com/repos/nette/utils/zipball/e67c4061eb40b9c113b218214e42cb5a0dda28f2",
"reference": "ce708655043c7050eb050df361c5e313cf708309", "reference": "e67c4061eb40b9c113b218214e42cb5a0dda28f2",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -2563,9 +2562,9 @@
], ],
"support": { "support": {
"issues": "https://github.com/nette/utils/issues", "issues": "https://github.com/nette/utils/issues",
"source": "https://github.com/nette/utils/tree/v4.0.6" "source": "https://github.com/nette/utils/tree/v4.0.7"
}, },
"time": "2025-03-30T21:06:30+00:00" "time": "2025-06-03T04:55:08+00:00"
}, },
{ {
"name": "nunomaduro/termwind", "name": "nunomaduro/termwind",
@ -3263,16 +3262,16 @@
}, },
{ {
"name": "ramsey/uuid", "name": "ramsey/uuid",
"version": "4.8.0", "version": "4.8.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/ramsey/uuid.git", "url": "https://github.com/ramsey/uuid.git",
"reference": "6700833915c00f890615fbcb653faed513836836" "reference": "fdf4dd4e2ff1813111bd0ad58d7a1ddbb5b56c28"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/ramsey/uuid/zipball/6700833915c00f890615fbcb653faed513836836", "url": "https://api.github.com/repos/ramsey/uuid/zipball/fdf4dd4e2ff1813111bd0ad58d7a1ddbb5b56c28",
"reference": "6700833915c00f890615fbcb653faed513836836", "reference": "fdf4dd4e2ff1813111bd0ad58d7a1ddbb5b56c28",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -3336,9 +3335,9 @@
], ],
"support": { "support": {
"issues": "https://github.com/ramsey/uuid/issues", "issues": "https://github.com/ramsey/uuid/issues",
"source": "https://github.com/ramsey/uuid/tree/4.8.0" "source": "https://github.com/ramsey/uuid/tree/4.8.1"
}, },
"time": "2025-06-01T02:32:15+00:00" "time": "2025-06-01T06:28:46+00:00"
}, },
{ {
"name": "symfony/clock", "name": "symfony/clock",
@ -6076,16 +6075,16 @@
}, },
{ {
"name": "filp/whoops", "name": "filp/whoops",
"version": "2.18.0", "version": "2.18.3",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/filp/whoops.git", "url": "https://github.com/filp/whoops.git",
"reference": "a7de6c3c6c3c022f5cfc337f8ede6a14460cf77e" "reference": "59a123a3d459c5a23055802237cb317f609867e5"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/filp/whoops/zipball/a7de6c3c6c3c022f5cfc337f8ede6a14460cf77e", "url": "https://api.github.com/repos/filp/whoops/zipball/59a123a3d459c5a23055802237cb317f609867e5",
"reference": "a7de6c3c6c3c022f5cfc337f8ede6a14460cf77e", "reference": "59a123a3d459c5a23055802237cb317f609867e5",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -6135,7 +6134,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/filp/whoops/issues", "issues": "https://github.com/filp/whoops/issues",
"source": "https://github.com/filp/whoops/tree/2.18.0" "source": "https://github.com/filp/whoops/tree/2.18.3"
}, },
"funding": [ "funding": [
{ {
@ -6143,7 +6142,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2025-03-15T12:00:00+00:00" "time": "2025-06-16T00:02:10+00:00"
}, },
{ {
"name": "hamcrest/hamcrest-php", "name": "hamcrest/hamcrest-php",
@ -6399,23 +6398,23 @@
}, },
{ {
"name": "nunomaduro/collision", "name": "nunomaduro/collision",
"version": "v8.8.0", "version": "v8.8.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/nunomaduro/collision.git", "url": "https://github.com/nunomaduro/collision.git",
"reference": "4cf9f3b47afff38b139fb79ce54fc71799022ce8" "reference": "44ccb82e3e21efb5446748d2a3c81a030ac22bd5"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/nunomaduro/collision/zipball/4cf9f3b47afff38b139fb79ce54fc71799022ce8", "url": "https://api.github.com/repos/nunomaduro/collision/zipball/44ccb82e3e21efb5446748d2a3c81a030ac22bd5",
"reference": "4cf9f3b47afff38b139fb79ce54fc71799022ce8", "reference": "44ccb82e3e21efb5446748d2a3c81a030ac22bd5",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"filp/whoops": "^2.18.0", "filp/whoops": "^2.18.1",
"nunomaduro/termwind": "^2.3.0", "nunomaduro/termwind": "^2.3.1",
"php": "^8.2.0", "php": "^8.2.0",
"symfony/console": "^7.2.5" "symfony/console": "^7.3.0"
}, },
"conflict": { "conflict": {
"laravel/framework": "<11.44.2 || >=13.0.0", "laravel/framework": "<11.44.2 || >=13.0.0",
@ -6423,15 +6422,15 @@
}, },
"require-dev": { "require-dev": {
"brianium/paratest": "^7.8.3", "brianium/paratest": "^7.8.3",
"larastan/larastan": "^3.2", "larastan/larastan": "^3.4.2",
"laravel/framework": "^11.44.2 || ^12.6", "laravel/framework": "^11.44.2 || ^12.18",
"laravel/pint": "^1.21.2", "laravel/pint": "^1.22.1",
"laravel/sail": "^1.41.0", "laravel/sail": "^1.43.1",
"laravel/sanctum": "^4.0.8", "laravel/sanctum": "^4.1.1",
"laravel/tinker": "^2.10.1", "laravel/tinker": "^2.10.1",
"orchestra/testbench-core": "^9.12.0 || ^10.1", "orchestra/testbench-core": "^9.12.0 || ^10.4",
"pestphp/pest": "^3.8.0", "pestphp/pest": "^3.8.2",
"sebastian/environment": "^7.2.0 || ^8.0" "sebastian/environment": "^7.2.1 || ^8.0"
}, },
"type": "library", "type": "library",
"extra": { "extra": {
@ -6494,7 +6493,7 @@
"type": "patreon" "type": "patreon"
} }
], ],
"time": "2025-04-03T14:33:09+00:00" "time": "2025-06-11T01:04:21+00:00"
}, },
{ {
"name": "phar-io/manifest", "name": "phar-io/manifest",
@ -6686,16 +6685,16 @@
}, },
{ {
"name": "phpunit/php-code-coverage", "name": "phpunit/php-code-coverage",
"version": "11.0.9", "version": "11.0.10",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
"reference": "14d63fbcca18457e49c6f8bebaa91a87e8e188d7" "reference": "1a800a7446add2d79cc6b3c01c45381810367d76"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/14d63fbcca18457e49c6f8bebaa91a87e8e188d7", "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/1a800a7446add2d79cc6b3c01c45381810367d76",
"reference": "14d63fbcca18457e49c6f8bebaa91a87e8e188d7", "reference": "1a800a7446add2d79cc6b3c01c45381810367d76",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -6752,15 +6751,27 @@
"support": { "support": {
"issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
"security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy",
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/11.0.9" "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/show"
}, },
"funding": [ "funding": [
{ {
"url": "https://github.com/sebastianbergmann", "url": "https://github.com/sebastianbergmann",
"type": "github" "type": "github"
},
{
"url": "https://liberapay.com/sebastianbergmann",
"type": "liberapay"
},
{
"url": "https://thanks.dev/u/gh/sebastianbergmann",
"type": "thanks_dev"
},
{
"url": "https://tidelift.com/funding/github/packagist/phpunit/php-code-coverage",
"type": "tidelift"
} }
], ],
"time": "2025-02-25T13:26:39+00:00" "time": "2025-06-18T08:56:18+00:00"
}, },
{ {
"name": "phpunit/php-file-iterator", "name": "phpunit/php-file-iterator",
@ -7009,16 +7020,16 @@
}, },
{ {
"name": "phpunit/phpunit", "name": "phpunit/phpunit",
"version": "11.5.21", "version": "11.5.24",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git", "url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "d565e2cdc21a7db9dc6c399c1fc2083b8010f289" "reference": "6b07ab1047155cf38f82dd691787a277782271dd"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/d565e2cdc21a7db9dc6c399c1fc2083b8010f289", "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/6b07ab1047155cf38f82dd691787a277782271dd",
"reference": "d565e2cdc21a7db9dc6c399c1fc2083b8010f289", "reference": "6b07ab1047155cf38f82dd691787a277782271dd",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -7032,7 +7043,7 @@
"phar-io/manifest": "^2.0.4", "phar-io/manifest": "^2.0.4",
"phar-io/version": "^3.2.1", "phar-io/version": "^3.2.1",
"php": ">=8.2", "php": ">=8.2",
"phpunit/php-code-coverage": "^11.0.9", "phpunit/php-code-coverage": "^11.0.10",
"phpunit/php-file-iterator": "^5.1.0", "phpunit/php-file-iterator": "^5.1.0",
"phpunit/php-invoker": "^5.0.1", "phpunit/php-invoker": "^5.0.1",
"phpunit/php-text-template": "^4.0.1", "phpunit/php-text-template": "^4.0.1",
@ -7090,7 +7101,7 @@
"support": { "support": {
"issues": "https://github.com/sebastianbergmann/phpunit/issues", "issues": "https://github.com/sebastianbergmann/phpunit/issues",
"security": "https://github.com/sebastianbergmann/phpunit/security/policy", "security": "https://github.com/sebastianbergmann/phpunit/security/policy",
"source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.21" "source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.24"
}, },
"funding": [ "funding": [
{ {
@ -7114,7 +7125,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2025-05-21T12:35:00+00:00" "time": "2025-06-20T11:31:02+00:00"
}, },
{ {
"name": "sebastian/cli-parser", "name": "sebastian/cli-parser",

View File

@ -94,5 +94,6 @@ return [
'template' => [ 'template' => [
'dir' => env('LDAP_TEMPLATE_DRIVER','templates'), 'dir' => env('LDAP_TEMPLATE_DRIVER','templates'),
'exclude_system' => env('LDAP_TEMPLATE_EXCLUDE_SYSTEM',FALSE),
], ],
]; ];

193
package-lock.json generated
View File

@ -2800,6 +2800,21 @@
"postcss": "^8.1.0" "postcss": "^8.1.0"
} }
}, },
"node_modules/available-typed-arrays": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
"integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==",
"license": "MIT",
"dependencies": {
"possible-typed-array-names": "^1.0.0"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/axios": { "node_modules/axios": {
"version": "1.10.0", "version": "1.10.0",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.10.0.tgz", "resolved": "https://registry.npmjs.org/axios/-/axios-1.10.0.tgz",
@ -3312,9 +3327,9 @@
} }
}, },
"node_modules/caniuse-lite": { "node_modules/caniuse-lite": {
"version": "1.0.30001723", "version": "1.0.30001724",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001723.tgz", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001724.tgz",
"integrity": "sha512-1R/elMjtehrFejxwmexeXAtae5UO9iSyFn6G/I806CYC/BLyyBk1EPhrKBkWhy6wM6Xnm47dSJQec+tLJ39WHw==", "integrity": "sha512-WqJo7p0TbHDOythNTqYujmaJTvtYRZrjpP8TCvH6Vb9CYJerJNKamKzIWOM4BkQatWj9H2lYulpdAQNBe7QhNA==",
"funding": [ "funding": [
{ {
"type": "opencollective", "type": "opencollective",
@ -4325,9 +4340,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/electron-to-chromium": { "node_modules/electron-to-chromium": {
"version": "1.5.170", "version": "1.5.171",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.170.tgz", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.171.tgz",
"integrity": "sha512-GP+M7aeluQo9uAyiTCxgIj/j+PrWhMlY7LFVj8prlsPljd0Fdg9AprlfUi+OCSFWy9Y5/2D/Jrj9HS8Z4rpKWA==", "integrity": "sha512-scWpzXEJEMrGJa4Y6m/tVotb0WuvNmasv3wWVzUAeCgKU0ToFOhUW6Z+xWnRQANMYGxN4ngJXIThgBJOqzVPCQ==",
"license": "ISC" "license": "ISC"
}, },
"node_modules/elliptic": { "node_modules/elliptic": {
@ -4908,6 +4923,21 @@
} }
} }
}, },
"node_modules/for-each": {
"version": "0.3.5",
"resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz",
"integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==",
"license": "MIT",
"dependencies": {
"is-callable": "^1.2.7"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/form-data": { "node_modules/form-data": {
"version": "4.0.3", "version": "4.0.3",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.3.tgz", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.3.tgz",
@ -5731,6 +5761,18 @@
"integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/is-callable": {
"version": "1.2.7",
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
"integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-core-module": { "node_modules/is-core-module": {
"version": "2.16.1", "version": "2.16.1",
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz",
@ -5836,6 +5878,21 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/is-typed-array": {
"version": "1.1.15",
"resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz",
"integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==",
"license": "MIT",
"dependencies": {
"which-typed-array": "^1.1.16"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-what": { "node_modules/is-what": {
"version": "3.14.1", "version": "3.14.1",
"resolved": "https://registry.npmjs.org/is-what/-/is-what-3.14.1.tgz", "resolved": "https://registry.npmjs.org/is-what/-/is-what-3.14.1.tgz",
@ -7051,21 +7108,53 @@
} }
}, },
"node_modules/pbkdf2": { "node_modules/pbkdf2": {
"version": "3.1.2", "version": "3.1.3",
"resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.3.tgz",
"integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", "integrity": "sha512-wfRLBZ0feWRhCIkoMB6ete7czJcnNnqRpcoWQBLqatqXXmelSRqfdDK4F3u9T2s2cXas/hQJcryI/4lAL+XTlA==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"create-hash": "^1.1.2", "create-hash": "~1.1.3",
"create-hmac": "^1.1.4", "create-hmac": "^1.1.7",
"ripemd160": "^2.0.1", "ripemd160": "=2.0.1",
"safe-buffer": "^5.0.1", "safe-buffer": "^5.2.1",
"sha.js": "^2.4.8" "sha.js": "^2.4.11",
"to-buffer": "^1.2.0"
}, },
"engines": { "engines": {
"node": ">=0.12" "node": ">=0.12"
} }
}, },
"node_modules/pbkdf2/node_modules/create-hash": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz",
"integrity": "sha512-snRpch/kwQhcdlnZKYanNF1m0RDlrCdSKQaH87w1FCFPVPNCQ/Il9QJKAX2jVBZddRdaHBMC+zXa9Gw9tmkNUA==",
"license": "MIT",
"dependencies": {
"cipher-base": "^1.0.1",
"inherits": "^2.0.1",
"ripemd160": "^2.0.0",
"sha.js": "^2.4.0"
}
},
"node_modules/pbkdf2/node_modules/hash-base": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/hash-base/-/hash-base-2.0.2.tgz",
"integrity": "sha512-0TROgQ1/SxE6KmxWSvXHvRj90/Xo1JvZShofnYF+f6ZsGtR4eES7WfrQzPalmyagfKZCXpVnitiRebZulWsbiw==",
"license": "MIT",
"dependencies": {
"inherits": "^2.0.1"
}
},
"node_modules/pbkdf2/node_modules/ripemd160": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.1.tgz",
"integrity": "sha512-J7f4wutN8mdbV08MJnXibYpCOPHR+yzy+iQ/AsjMv2j8cLavQ8VGagDFUwwTAdF8FmRKVeNpbTTEwNHCW1g94w==",
"license": "MIT",
"dependencies": {
"hash-base": "^2.0.0",
"inherits": "^2.0.1"
}
},
"node_modules/pe7-icon": { "node_modules/pe7-icon": {
"version": "1.0.4", "version": "1.0.4",
"resolved": "https://registry.npmjs.org/pe7-icon/-/pe7-icon-1.0.4.tgz", "resolved": "https://registry.npmjs.org/pe7-icon/-/pe7-icon-1.0.4.tgz",
@ -7117,6 +7206,15 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/possible-typed-array-names": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz",
"integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/postcss": { "node_modules/postcss": {
"version": "8.5.6", "version": "8.5.6",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz",
@ -8996,9 +9094,9 @@
} }
}, },
"node_modules/terser": { "node_modules/terser": {
"version": "5.43.0", "version": "5.43.1",
"resolved": "https://registry.npmjs.org/terser/-/terser-5.43.0.tgz", "resolved": "https://registry.npmjs.org/terser/-/terser-5.43.1.tgz",
"integrity": "sha512-CqNNxKSGKSZCunSvwKLTs8u8sGGlp27sxNZ4quGh0QeNuyHM0JSEM/clM9Mf4zUp6J+tO2gUXhgXT2YMMkwfKQ==", "integrity": "sha512-+6erLbBm0+LROX2sPXlUYx/ux5PyE9K/a92Wrt6oA+WDAoFTdpHE5tCYCI5PNzq2y8df4rA+QgHLJuR4jNymsg==",
"license": "BSD-2-Clause", "license": "BSD-2-Clause",
"dependencies": { "dependencies": {
"@jridgewell/source-map": "^0.3.3", "@jridgewell/source-map": "^0.3.3",
@ -9130,6 +9228,26 @@
"integrity": "sha512-okFlQcoGTi4LQBG/PgSYblw9VOyptsz2KJZqc6qtgGdes8VktzUQkj4BI2blit072iS8VODNcMA+tvnS9dnuMA==", "integrity": "sha512-okFlQcoGTi4LQBG/PgSYblw9VOyptsz2KJZqc6qtgGdes8VktzUQkj4BI2blit072iS8VODNcMA+tvnS9dnuMA==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/to-buffer": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.1.tgz",
"integrity": "sha512-tB82LpAIWjhLYbqjx3X4zEeHN6M8CiuOEy2JY8SEQVdYRe3CCHOFaqrBW1doLDrfpWhplcW7BL+bO3/6S3pcDQ==",
"license": "MIT",
"dependencies": {
"isarray": "^2.0.5",
"safe-buffer": "^5.2.1",
"typed-array-buffer": "^1.0.3"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/to-buffer/node_modules/isarray": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
"integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
"license": "MIT"
},
"node_modules/to-regex-range": { "node_modules/to-regex-range": {
"version": "5.0.1", "version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
@ -9176,6 +9294,20 @@
"node": ">= 0.6" "node": ">= 0.6"
} }
}, },
"node_modules/typed-array-buffer": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz",
"integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==",
"license": "MIT",
"dependencies": {
"call-bound": "^1.0.3",
"es-errors": "^1.3.0",
"is-typed-array": "^1.1.14"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/undici-types": { "node_modules/undici-types": {
"version": "7.8.0", "version": "7.8.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.8.0.tgz", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.8.0.tgz",
@ -9791,9 +9923,9 @@
} }
}, },
"node_modules/webpack/node_modules/webpack-sources": { "node_modules/webpack/node_modules/webpack-sources": {
"version": "3.3.2", "version": "3.3.3",
"resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.2.tgz", "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.3.tgz",
"integrity": "sha512-ykKKus8lqlgXX/1WjudpIEjqsafjOTcOJqxnAbMLAu/KCsDCJ6GBtvscewvTkrn24HsnvFwrSCbenFrhtcCsAA==", "integrity": "sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==",
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=10.13.0" "node": ">=10.13.0"
@ -9855,6 +9987,27 @@
"node": ">= 8" "node": ">= 8"
} }
}, },
"node_modules/which-typed-array": {
"version": "1.1.19",
"resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz",
"integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==",
"license": "MIT",
"dependencies": {
"available-typed-arrays": "^1.0.7",
"call-bind": "^1.0.8",
"call-bound": "^1.0.4",
"for-each": "^0.3.5",
"get-proto": "^1.0.1",
"gopd": "^1.2.0",
"has-tostringtag": "^1.0.2"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/wildcard": { "node_modules/wildcard": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz",

View File

@ -15,7 +15,7 @@ function getNode(item) {
$.ajax({ $.ajax({
url: '/frame', url: '/frame',
method: 'POST', method: 'POST',
data: { key: item }, data: { _key: item },
dataType: 'html', dataType: 'html',
beforeSend: function() { beforeSend: function() {
content = $('.main-content') content = $('.main-content')
@ -96,7 +96,7 @@ $(document).ready(function() {
lazyLoad: function(event,data) { lazyLoad: function(event,data) {
data.result = { data.result = {
url: '/ajax/children', url: '/ajax/children',
data: {key: data.node.data.item,depth: 1} data: {_key: data.node.data.item,depth: 1}
}; };
expandChildren(data.tree.rootNode); expandChildren(data.tree.rootNode);

23
public/js/template.js Normal file
View File

@ -0,0 +1,23 @@
/* JavaScript template engine abstraction layer */
/* Currently implemented for jquery */
// Get a value from an attribute
function get_attribute(attribute,start,end) {
var val = $('#'+attribute).find('input').val();
return ((start !== undefined) && (end !== undefined))
? val.substring(start,end)
: val;
}
// Put a value to an attribute
function put_attribute(attribute,result) {
// Get the value, if the value hasnt changed, then we dont need to do anything
if (get_attribute(attribute) === result)
return;
$('#'+attribute)
.find('input')
.val(result)
.trigger('change');
}

81
public/js/toAscii.js Normal file
View File

@ -0,0 +1,81 @@
//
// Purpose of this file is to remap characters as ASCII characters
//
//
var to_ascii_array = new Array();
to_ascii_array['à'] = 'a';
to_ascii_array['á'] = 'a';
to_ascii_array['â'] = 'a';
to_ascii_array['À'] = 'a';
to_ascii_array['ã'] = 'a';
to_ascii_array['Ã¥'] = 'a';
to_ascii_array['À'] = 'A';
to_ascii_array['Á'] = 'A';
to_ascii_array['Ä'] = 'A';
to_ascii_array['Â'] = 'A';
to_ascii_array['Ã'] = 'A';
to_ascii_array['Å'] = 'A';
to_ascii_array['é'] = 'e';
to_ascii_array['Ú'] = 'e';
to_ascii_array['ë'] = 'e';
to_ascii_array['ê'] = 'e';
to_ascii_array['€'] = 'E';
to_ascii_array['ï'] = 'i';
to_ascii_array['î'] = 'i';
to_ascii_array['ì'] = 'i';
to_ascii_array['í'] = 'i';
to_ascii_array['Ï'] = 'I';
to_ascii_array['Î'] = 'I';
to_ascii_array['Ì'] = 'I';
to_ascii_array['Í'] = 'I';
to_ascii_array['ò'] = 'o';
to_ascii_array['ó'] = 'o';
to_ascii_array['ÃŽ'] = 'o';
to_ascii_array['õ'] = 'o';
to_ascii_array['ö'] = 'o';
to_ascii_array['Þ'] = 'o';
to_ascii_array['Ò'] = 'O';
to_ascii_array['Ó'] = 'O';
to_ascii_array['Ô'] = 'O';
to_ascii_array['Õ'] = 'O';
to_ascii_array['Ö'] = 'O';
to_ascii_array['Ø'] = 'O';
to_ascii_array['ù'] = 'u';
to_ascii_array['ú'] = 'u';
to_ascii_array['Ì'] = 'u';
to_ascii_array['û'] = 'u';
to_ascii_array['Ù'] = 'U';
to_ascii_array['Ú'] = 'U';
to_ascii_array['Ü'] = 'U';
to_ascii_array['Û'] = 'U';
to_ascii_array['Ê'] = 'ae';
to_ascii_array['Æ'] = 'AE';
to_ascii_array['Ü'] = 'y';
to_ascii_array['ÿ'] = 'y';
to_ascii_array['ß'] = 'SS';
to_ascii_array['Ç'] = 'C';
to_ascii_array['ç'] = 'c';
to_ascii_array['Ñ'] = 'N';
to_ascii_array['ñ'] = 'n';
to_ascii_array['¢'] = 'c';
to_ascii_array['©'] = '(C)';
to_ascii_array['®'] = '(R)';
to_ascii_array['«'] = '<<';
to_ascii_array['»'] = '>>';
function toAscii(text) {
//var text = field.value;
var output = '';
for (position=0; position < text.length; position++) {
var tmp = text.substring(position,position+1);
if (to_ascii_array[tmp] !== undefined)
tmp = to_ascii_array[tmp];
output += tmp;
}
return output;
}

View File

@ -18,3 +18,8 @@
<!-- Any Custom JS --> <!-- Any Custom JS -->
<script src="{{ asset('js/custom.js') }}"></script> <script src="{{ asset('js/custom.js') }}"></script>
@endif @endif
@if(file_exists('js/template.js'))
<!-- Template Engine JS -->
<script src="{{ asset('js/template.js') }}"></script>
@endif

View File

@ -7,6 +7,15 @@
<span class="d-flex justify-content-between"> <span class="d-flex justify-content-between">
<span style="width: 20em;"> <span style="width: 20em;">
<strong class="align-middle"><abbr title="{{ $o->description }}">{{ $o->name }}</abbr></strong> <strong class="align-middle"><abbr title="{{ $o->description }}">{{ $o->name }}</abbr></strong>
@if($new)
@if($template?->onChangeAttribute($o->name_lc))
<sup data-bs-toggle="tooltip" title="@lang('Value triggers an update to another attribute by template')"><i class="fas fa-keyboard"></i></sup>
@endif
@if ($template?->onChangeTarget($o->name_lc))
<sup data-bs-toggle="tooltip" title="@lang('Value calculated by template')"><i class="fas fa-wand-magic-sparkles"></i></sup>
@endif
@endif
@if($o->hints->count()) @if($o->hints->count())
<sup> <sup>
[ [

View File

@ -34,3 +34,15 @@
</div> </div>
</div> </div>
</x-attribute.layout> </x-attribute.layout>
@if($new && ($x=$template?->onChange($o->name))?->count())
@section('page-scripts')
<!-- START: ONCHANGE PROCESSING {{ $o->name }} -->
<script type="text/javascript">
$('#{{ $o->name_lc }}').on('change',function() {
{!! $x->join('') !!}
});
</script>
<!-- END: ONCHANGE PROCESSING {{ $o->name }} -->
@append
@endif

View File

@ -4,7 +4,7 @@
@foreach(($o->tagValues($langtag)->count() ? $o->tagValues($langtag) : [$langtag => NULL]) as $key => $value) @foreach(($o->tagValues($langtag)->count() ? $o->tagValues($langtag) : [$langtag => NULL]) as $key => $value)
@if($edit) @if($edit)
<div class="input-group has-validation"> <div class="input-group has-validation">
<x-form.select id="userpassword_hash_{{$loop->index}}{{$template?->name ?? ''}}" name="userpassword_hash[{{ $langtag }}][]" :value="$o->hash($new ? '' : ($value ?? ''))->id()" :options="$helpers" allowclear="false" :disabled="! $new"/> <x-form.select id="userpassword_hash_{{$loop->index}}{{$template?->name ?? ''}}" name="_userpassword_hash[{{ $langtag }}][]" :value="$o->hash($new ? '' : ($value ?? ''))->id()" :options="$helpers" allowclear="false" :disabled="! $new"/>
<input type="password" @class(['form-control','is-invalid'=>($e=$errors->get($o->name_lc.'.'.$langtag.'.'.$loop->index)),'mb-1','border-focus'=>! $o->tagValuesOld($langtag)->contains($value),'bg-success-subtle'=>$updated]) name="{{ $o->name_lc }}[{{ $langtag }}][]" value="{{ Arr::get(old($o->name_lc),$langtag.'.'.$loop->index,$value ? md5($value) : '') }}" @readonly(! $new)> <input type="password" @class(['form-control','is-invalid'=>($e=$errors->get($o->name_lc.'.'.$langtag.'.'.$loop->index)),'mb-1','border-focus'=>! $o->tagValuesOld($langtag)->contains($value),'bg-success-subtle'=>$updated]) name="{{ $o->name_lc }}[{{ $langtag }}][]" value="{{ Arr::get(old($o->name_lc),$langtag.'.'.$loop->index,$value ? md5($value) : '') }}" @readonly(! $new)>
<div class="invalid-feedback pb-2"> <div class="invalid-feedback pb-2">

View File

@ -3,24 +3,24 @@
@foreach(($o->values->count() ? $o->values : [NULL]) as $value) @foreach(($o->values->count() ? $o->values : [NULL]) 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','is-invalid'=>$errors->get('_rdn')]) id="rdn" name="_rdn">
<option value=""></option> <option value=""></option>
@foreach($o->attrs->map(fn($item)=>['id'=>$item,'value'=>$item]) as $option) @foreach($o->attrs->map(fn($item)=>['id'=>$item,'value'=>$item]) as $option)
@continue(! Arr::get($option,'value')) @continue(! Arr::get($option,'value'))
<option value="{{ strtolower(Arr::get($option,'id')) }}" @selected(Arr::get($option,'id') == old('rdn',$value ?? ''))>{{ Arr::get($option,'value') }}</option> <option value="{{ strtolower(Arr::get($option,'id')) }}" @selected(Arr::get($option,'id') == old('_rdn',$value ?? ''))>{{ Arr::get($option,'value') }}</option>
@endforeach @endforeach
</select> </select>
<span class="input-group-text">=</span> <span class="input-group-text">=</span>
<input type="text" @class(['form-control','is-invalid'=>$errors->get('rdn_value')]) id="rdn_value" name="rdn_value" value="{{ old('rdn_value') }}" placeholder="rdn"> <input type="text" @class(['form-control','is-invalid'=>$errors->get('_rdn_value')]) id="rdn_value" name="_rdn_value" value="{{ old('_rdn_value') }}" placeholder="rdn">
<label class="input-group-text" for="inputGroupSelect02">,{{ $o->base }}</label> <label class="input-group-text" for="inputGroupSelect02">,{{ $o->base }}</label>
<div class="invalid-feedback pb-2"> <div class="invalid-feedback pb-2">
@error('rdn') @error('_rdn')
{{ $message }} {{ $message }}
@enderror @enderror
@error('rdn_value') @error('_rdn_value')
{{ $message }} {{ $message }}
@enderror @enderror
</div> </div>

View File

@ -6,10 +6,10 @@
<div class="card-body"> <div class="card-body">
<div class="tab-content"> <div class="tab-content">
@php($up=(session()->pull('updated') ?: collect())) @php($up=(session()->get('updated') ?: collect()))
@foreach($o->getVisibleAttributes()->filter(fn($item)=>$template->attributes->map('strtolower')->contains($item->name_lc)) as $ao) @foreach($o->getVisibleAttributes()->filter(fn($item)=>$template->attributes->map('strtolower')->contains($item->name_lc)) as $ao)
<x-attribute-type :o="$ao" :edit="TRUE" :new="FALSE" :template="$template" :updated="$up->contains($ao->name_lc)"/> <x-attribute-type :o="$ao" :edit="TRUE" :new="FALSE" :template="$template" :updated="$up->contains($ao->name)"/>
@endforeach @endforeach
</div> </div>
</div> </div>

View File

@ -24,8 +24,8 @@
<form id="dn-create" method="POST" class="needs-validation" action="{{ url((int)$step === 2 ? 'entry/create' : 'entry/add') }}" enctype="multipart/form-data" novalidate> <form id="dn-create" method="POST" class="needs-validation" action="{{ url((int)$step === 2 ? 'entry/create' : 'entry/add') }}" enctype="multipart/form-data" novalidate>
@csrf @csrf
<input type="hidden" name="key" value="{{ Crypt::encryptString('*create|'.$container) }}"> <input type="hidden" name="_key" value="{{ Crypt::encryptString('*create|'.$container) }}">
<input type="hidden" name="step" value="{{ $step }}"> <input type="hidden" name="_step" value="{{ $step }}">
@switch($step) @switch($step)
@case(1) @case(1)
@ -63,10 +63,11 @@
@break @break
@case(2) @case(2)
<x-attribute-type :o="$o->getObject('rdn')" :edit="TRUE" :new="FALSE" :updated="FALSE"/> <input type="hidden" name="_template" value="{{ $template?->file }}">
<x-attribute-type :o="$o->getObject('rdn')" :edit="TRUE" :new="TRUE" :template="$template" :updated="FALSE"/>
@foreach($o->getVisibleAttributes() as $ao) @foreach($o->getVisibleAttributes() as $ao)
<x-attribute-type :o="$ao" :edit="TRUE" :new="FALSE" :template="$template" :updated="FALSE"/> <x-attribute-type :o="$ao" :edit="TRUE" :new="TRUE" :template="$template" :updated="FALSE"/>
@endforeach @endforeach
@if(! $template) @if(! $template)

View File

@ -101,7 +101,7 @@
<div class="tab-content"> <div class="tab-content">
@php($up=(session()->pull('updated') ?: collect())) @php($up=(session()->pull('updated') ?: collect()))
@foreach($o->getVisibleAttributes() as $ao) @foreach($o->getVisibleAttributes() as $ao)
<x-attribute-type :o="$ao" :edit="TRUE" :new="FALSE" :updated="$up->contains($ao->name_lc)"/> <x-attribute-type :o="$ao" :edit="TRUE" :new="FALSE" :template="$template ?? NULL" :updated="$up->contains($ao->name)"/>
@endforeach @endforeach
@include('fragment.dn.add_attr') @include('fragment.dn.add_attr')
@ -124,7 +124,7 @@
<!-- Internal Attributes --> <!-- Internal Attributes -->
<div class="tab-pane mt-3" id="internal" role="tabpanel"> <div class="tab-pane mt-3" id="internal" role="tabpanel">
@foreach($o->getInternalAttributes() as $ao) @foreach($o->getInternalAttributes() as $ao)
<x-attribute-type :o="$ao" :edit="FALSE" :new="FALSE" :updated="FALSE"/> <x-attribute-type :o="$ao" :edit="FALSE" :new="FALSE" :template="$template ?? NULL" :updated="FALSE"/>
@endforeach @endforeach
</div> </div>
</div> </div>

View File

@ -15,7 +15,7 @@
<div class="main-card mb-3 card"> <div class="main-card mb-3 card">
<form id="import-form" action="{{ url('import/process/ldif') }}" method="POST" enctype="multipart/form-data"> <form id="import-form" action="{{ url('import/process/ldif') }}" method="POST" enctype="multipart/form-data">
@csrf @csrf
<input type="hidden" name="key" value="{{ Crypt::encryptString('*import|_NOP') }}"> <input type="hidden" name="_key" value="{{ Crypt::encryptString('*import|_NOP') }}">
<div class="card-header"> <div class="card-header">
@lang('LDIF Import') @lang('LDIF Import')

View File

@ -44,6 +44,12 @@
<li class="ps-0 p-1"> <li class="ps-0 p-1">
<i class="fas fa-fw fa-sitemap me-2"></i> Hierarchical Tree View <i class="fas fa-fw fa-sitemap me-2"></i> Hierarchical Tree View
</li> </li>
<li class="ps-0 p-1">
<i class="fas fa-fw fa-clone me-2"></i> Creation and Modification Templates
</li>
<li class="ps-0 p-1">
<i class="fas fa-fw fa-magnifying-glass-chart me-2"></i> Data Rich Attribute Values
</li>
<li class="ps-0 p-1"> <li class="ps-0 p-1">
<i class="fas fa-fw fa-language me-2"></i> Multi-language Support <i class="fas fa-fw fa-language me-2"></i> Multi-language Support
</li> </li>

View File

@ -4,7 +4,7 @@
"enabled": true, "enabled": true,
"icon": "fa-user", "icon": "fa-user",
"rdn": "cn", "rdn": "cn",
"regexp": "/^ou=.+,o=.+,?/", "regexp": "/^ou=.+,?/",
"objectclasses": [ "objectclasses": [
"inetOrgPerson", "inetOrgPerson",
@ -15,7 +15,7 @@
"givenName": { "givenName": {
"display": "First Name", "display": "First Name",
"onchange": [ "onchange": [
"=autoFill(cn;%givenName% %sn%)", "=autoFill(cn;%givenName% %sn/U%)",
"=autoFill(uid;%givenName|0-1/l%%sn/l%)" "=autoFill(uid;%givenName|0-1/l%%sn/l%)"
], ],
"order": 1 "order": 1
@ -23,7 +23,7 @@
"sn": { "sn": {
"display": "Last Name", "display": "Last Name",
"onchange": [ "onchange": [
"=autoFill(cn;%givenName% %sn%)", "=autoFill(cn;%givenName% %sn/U%)",
"=autoFill(uid;%givenName|0-1/l%%sn/l%)" "=autoFill(uid;%givenName|0-1/l%%sn/l%)"
], ],
"order": 2 "order": 2

View File

@ -34,7 +34,7 @@ class ImportTest extends TestCase
->from('/import') ->from('/import')
->post('/import/process/ldif',[ ->post('/import/process/ldif',[
'_token' => csrf_token(), '_token' => csrf_token(),
'key'=>Crypt::encryptString('*import|_NOP'), '_key'=>Crypt::encryptString('*import|_NOP'),
'file' => $file, 'file' => $file,
]); ]);