Compare commits

...

6 Commits

Author SHA1 Message Date
d4509747df Update npm assets to make dependabot happier
All checks were successful
Create Docker Image / Test Application (x86_64) (push) Successful in 3m27s
Create Docker Image / Build Docker Image (x86_64) (push) Successful in 1m25s
Create Docker Image / Build Docker Image (arm64) (push) Successful in 2m51s
Create Docker Image / Final Docker Image Manifest (push) Successful in 10s
2025-06-19 18:09:39 +10:00
2d732e5d52 Remove our highlighted item from the tree, when we click on the top-menu buttons
All checks were successful
Create Docker Image / Test Application (x86_64) (push) Successful in 28s
Create Docker Image / Build Docker Image (x86_64) (push) Successful in 1m39s
Create Docker Image / Build Docker Image (arm64) (push) Successful in 2m53s
Create Docker Image / Final Docker Image Manifest (push) Successful in 10s
2025-06-19 17:46:13 +10:00
d294c9449d Fix page expired 419 started showing a page expired message, instead of refreshing the session and loading the clicked item on the tree 2025-06-19 17:22:24 +10:00
deefd9be43 Fix for when specifying multiple base DNs with LDAP_BASE_DN, and the user doesnt have access to the first one. 2025-06-19 16:15:22 +10:00
59cf0d337e Add alert for DN logins that dont exist. Might be attempts to use the rootdn which is not supported.
Closes #345
2025-06-19 16:15:22 +10:00
c4b1d9ec51 Pass the template object to the attributes, so we can leverage template rules when rendering attributes 2025-06-19 16:15:22 +10:00
29 changed files with 364 additions and 142 deletions

View File

@ -14,3 +14,4 @@ LDAP_HOST=
LDAP_USERNAME= LDAP_USERNAME=
LDAP_PASSWORD= LDAP_PASSWORD=
LDAP_CACHE=false LDAP_CACHE=false
LDAP_ALERT_ROOTDN=true

View File

@ -3,7 +3,7 @@ run-name: ${{ gitea.actor }} Building Docker Image 🐳
on: [push] on: [push]
env: env:
DOCKER_HOST: tcp://127.0.0.1:2375 DOCKER_HOST: tcp://127.0.0.1:2375
ASSETS: 3fcb8707 ASSETS: 2d732e5
jobs: jobs:
test: test:

View File

@ -7,6 +7,7 @@ use Illuminate\Support\Arr;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use App\Classes\LDAP\Schema\AttributeType; use App\Classes\LDAP\Schema\AttributeType;
use App\Classes\Template;
use App\Exceptions\InvalidUsage; use App\Exceptions\InvalidUsage;
use App\Ldap\Entry; use App\Ldap\Entry;
@ -326,10 +327,10 @@ class Attribute implements \Countable, \ArrayAccess
* @param bool $old Use old value * @param bool $old Use old value
* @param bool $new Enable adding values * @param bool $new Enable adding values
* @param bool $updated Has the entry been updated (uses rendering highlights)) * @param bool $updated Has the entry been updated (uses rendering highlights))
* @param string|null $template * @param Template|null $template
* @return View * @return View
*/ */
public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,bool $updated=FALSE,?string $template=NULL): View public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,bool $updated=FALSE,?Template $template=NULL): View
{ {
if ($this->is_internal) if ($this->is_internal)
// @note Internal attributes cannot be edited // @note Internal attributes cannot be edited

View File

@ -5,7 +5,7 @@ namespace App\Classes\LDAP\Attribute\Binary;
use Illuminate\Contracts\View\View; use Illuminate\Contracts\View\View;
use App\Classes\LDAP\Attribute\Binary; use App\Classes\LDAP\Attribute\Binary;
use App\Ldap\Entry; use App\Classes\Template;
use App\Traits\MD5Updates; use App\Traits\MD5Updates;
/** /**
@ -15,7 +15,7 @@ final class JpegPhoto extends Binary
{ {
use MD5Updates; use MD5Updates;
public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,bool $updated=FALSE,?string $template=NULL): View public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,bool $updated=FALSE,?Template $template=NULL): View
{ {
return view('components.attribute.binary.jpegphoto') return view('components.attribute.binary.jpegphoto')
->with('o',$this) ->with('o',$this)

View File

@ -2,9 +2,6 @@
namespace App\Classes\LDAP\Attribute; namespace App\Classes\LDAP\Attribute;
use Carbon\Carbon;
use Illuminate\Support\Arr;
use App\Classes\LDAP\Attribute; use App\Classes\LDAP\Attribute;
use App\Traits\MD5Updates; use App\Traits\MD5Updates;

View File

@ -3,7 +3,6 @@
namespace App\Classes\LDAP\Attribute; namespace App\Classes\LDAP\Attribute;
use Illuminate\Support\Arr; use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Log;
use App\Classes\LDAP\Attribute; use App\Classes\LDAP\Attribute;

View File

@ -5,14 +5,14 @@ namespace App\Classes\LDAP\Attribute\Internal;
use Illuminate\Contracts\View\View; use Illuminate\Contracts\View\View;
use App\Classes\LDAP\Attribute\Internal; use App\Classes\LDAP\Attribute\Internal;
use App\Ldap\Entry; use App\Classes\Template;
/** /**
* Represents an attribute whose values are timestamps * Represents an attribute whose values are timestamps
*/ */
final class Timestamp extends Internal final class Timestamp extends Internal
{ {
public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,bool $updated=FALSE,?string $template=NULL): View public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,bool $updated=FALSE,?Template $template=NULL): View
{ {
// @note Internal attributes cannot be edited // @note Internal attributes cannot be edited
return view('components.attribute.internal.timestamp') return view('components.attribute.internal.timestamp')

View File

@ -5,7 +5,7 @@ namespace App\Classes\LDAP\Attribute;
use Illuminate\Contracts\View\View; use Illuminate\Contracts\View\View;
use App\Classes\LDAP\Attribute; use App\Classes\LDAP\Attribute;
use App\Ldap\Entry; use App\Classes\Template;
use App\Traits\MD5Updates; use App\Traits\MD5Updates;
/** /**
@ -17,7 +17,7 @@ final class KrbPrincipalKey extends Attribute
protected(set) bool $no_attr_tags = TRUE; protected(set) bool $no_attr_tags = TRUE;
public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,bool $updated=FALSE,?string $template=NULL): View public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,bool $updated=FALSE,?Template $template=NULL): View
{ {
return view('components.attribute.krbprincipalkey') return view('components.attribute.krbprincipalkey')
->with('o',$this) ->with('o',$this)

View File

@ -6,7 +6,7 @@ use Illuminate\Contracts\View\View;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use App\Classes\LDAP\Attribute; use App\Classes\LDAP\Attribute;
use App\Ldap\Entry; use App\Classes\Template;
/** /**
* Represents an attribute whose value is a Kerberos Ticket Flag * Represents an attribute whose value is a Kerberos Ticket Flag
@ -50,7 +50,7 @@ final class KrbTicketFlags extends Attribute
return $helpers; return $helpers;
} }
public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,bool $updated=FALSE,?string $template=NULL): View public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,bool $updated=FALSE,?Template $template=NULL): View
{ {
return view('components.attribute.krbticketflags') return view('components.attribute.krbticketflags')
->with('o',$this) ->with('o',$this)

View File

@ -6,7 +6,7 @@ use Illuminate\Contracts\View\View;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use App\Classes\LDAP\Attribute; use App\Classes\LDAP\Attribute;
use App\Ldap\Entry; use App\Classes\Template;
/** /**
* Represents an ObjectClass Attribute * Represents an ObjectClass Attribute
@ -70,7 +70,7 @@ final class ObjectClass extends Attribute
->contains($value); ->contains($value);
} }
public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,bool $updated=FALSE,?string $template=NULL): View public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,bool $updated=FALSE,?Template $template=NULL): View
{ {
return view('components.attribute.objectclass') return view('components.attribute.objectclass')
->with('o',$this) ->with('o',$this)

View File

@ -7,7 +7,7 @@ use Illuminate\Support\Arr;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use App\Classes\LDAP\Attribute; use App\Classes\LDAP\Attribute;
use App\Ldap\Entry; use App\Classes\Template;
use App\Traits\MD5Updates; use App\Traits\MD5Updates;
/** /**
@ -80,7 +80,7 @@ final class Password extends Attribute
return ($helpers=static::helpers())->has($id) ? new ($helpers->get($id)) : NULL; return ($helpers=static::helpers())->has($id) ? new ($helpers->get($id)) : NULL;
} }
public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,bool $updated=FALSE,?string $template=NULL): View public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,bool $updated=FALSE,?Template $template=NULL): View
{ {
return view('components.attribute.password') return view('components.attribute.password')
->with('o',$this) ->with('o',$this)

View File

@ -6,7 +6,7 @@ use Illuminate\Contracts\View\View;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use App\Classes\LDAP\Attribute; use App\Classes\LDAP\Attribute;
use App\Ldap\Entry; use App\Classes\Template;
/** /**
* Represents the RDN for an Entry * Represents the RDN for an Entry
@ -35,7 +35,7 @@ final class RDN extends Attribute
]); ]);
} }
public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,bool $updated=FALSE,?string $template=NULL): View public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,bool $updated=FALSE,?Template $template=NULL): View
{ {
return view('components.attribute.rdn') return view('components.attribute.rdn')
->with('o',$this); ->with('o',$this);

View File

@ -2,12 +2,10 @@
namespace App\Classes\LDAP\Attribute; namespace App\Classes\LDAP\Attribute;
use Illuminate\Contracts\View\View;
use Illuminate\Support\Arr; use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Cache;
use App\Classes\LDAP\Attribute; use App\Classes\LDAP\Attribute;
use App\Ldap\Entry;
/** /**
* Represents an attribute whose values are schema related * Represents an attribute whose values are schema related

View File

@ -5,14 +5,14 @@ namespace App\Classes\LDAP\Attribute\Schema;
use Illuminate\Contracts\View\View; use Illuminate\Contracts\View\View;
use App\Classes\LDAP\Attribute\Schema; use App\Classes\LDAP\Attribute\Schema;
use App\Ldap\Entry; use App\Classes\Template;
/** /**
* Represents a Generic Schema Attribute * Represents a Generic Schema Attribute
*/ */
class Generic extends Schema class Generic extends Schema
{ {
public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,bool $updated=FALSE,?string $template=NULL): View public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,bool $updated=FALSE,?Template $template=NULL): View
{ {
// @note Schema attributes cannot be edited // @note Schema attributes cannot be edited
return view('components.attribute.schema.generic') return view('components.attribute.schema.generic')

View File

@ -5,7 +5,7 @@ namespace App\Classes\LDAP\Attribute\Schema;
use Illuminate\Contracts\View\View; use Illuminate\Contracts\View\View;
use App\Classes\LDAP\Attribute\Schema; use App\Classes\LDAP\Attribute\Schema;
use App\Ldap\Entry; use App\Classes\Template;
/** /**
* Represents a Mechanisms Attribute * Represents a Mechanisms Attribute
@ -34,7 +34,7 @@ final class Mechanisms extends Schema
return parent::_get(config_path('ldap_supported_saslmechanisms.txt'),$string,$key); return parent::_get(config_path('ldap_supported_saslmechanisms.txt'),$string,$key);
} }
public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,bool $updated=FALSE,?string $template=NULL): View public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,bool $updated=FALSE,?Template $template=NULL): View
{ {
// @note Schema attributes cannot be edited // @note Schema attributes cannot be edited
return view('components.attribute.schema.mechanisms') return view('components.attribute.schema.mechanisms')

View File

@ -5,7 +5,7 @@ namespace App\Classes\LDAP\Attribute\Schema;
use Illuminate\Contracts\View\View; use Illuminate\Contracts\View\View;
use App\Classes\LDAP\Attribute\Schema; use App\Classes\LDAP\Attribute\Schema;
use App\Ldap\Entry; use App\Classes\Template;
/** /**
* Represents an OID Attribute * Represents an OID Attribute
@ -35,7 +35,7 @@ final class OID extends Schema
return parent::_get(config_path('ldap_supported_oids.txt'),$string,$key); return parent::_get(config_path('ldap_supported_oids.txt'),$string,$key);
} }
public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,bool $updated=FALSE,?string $template=NULL): View public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,bool $updated=FALSE,?Template $template=NULL): View
{ {
// @note Schema attributes cannot be edited // @note Schema attributes cannot be edited
return view('components.attribute.schema.oid') return view('components.attribute.schema.oid')

View File

@ -20,6 +20,8 @@ class Template
$this->file = $file; $this->file = $file;
try { try {
// @todo Load in the proper attribute objects and objectclass objects
// @todo Make sure we have a structural objectclass, or make the template invalid
$this->template = json_decode($td->get($file),null,512,JSON_OBJECT_AS_ARRAY|JSON_THROW_ON_ERROR); $this->template = json_decode($td->get($file),null,512,JSON_OBJECT_AS_ARRAY|JSON_THROW_ON_ERROR);
} catch (\JsonException $e) { } catch (\JsonException $e) {
@ -47,8 +49,159 @@ class Template
return array_key_exists($key,$this->template); return array_key_exists($key,$this->template);
} }
public function __toString(): string private function autofill()
{ {
return $this->invalid ? '' : Arr::get($this->template,'title','No Template Name'); /*
autoFill:string
string is a literal string, and 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.
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.
K: 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
*/
if (! preg_match('/;/',$arg)) {
system_message(array(
'title'=>_('Problem with autoFill() in template'),
'body'=>sprintf('%s (<b>%s</b>)',_('There is only 1 argument, when there should be two'),$attribute->getName(false)),
'type'=>'warn'));
return;
}
list($attr,$string) = preg_split('(([^,]+);(.*))',$arg,-1,PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
preg_match_all('/%(\w+)(\|[0-9]*-[0-9]*)?(\/[KklTUA]+)?(?:\|(.))?%/U',$string,$matchall);
//print"<PRE>";print_r($matchall); //0 = highlevel match, 1 = attr, 2 = subst, 3 = mod, 4 = delimiter
if (! isset($attribute->js['autoFill']))
$attribute->js['autoFill'] = '';
$formula = $string;
$formula = preg_replace('/^([^%])/','\'$1',$formula);
$formula = preg_replace('/([^%])$/','$1\'',$formula);
# Check that our attributes match our schema attributes.
foreach ($matchall[1] as $index => $checkattr) {
$sattr = $this->getServer()->getSchemaAttribute($checkattr);
# If the attribute is the same as in the XML file, then dont need to do anything.
if (! $sattr || ! strcasecmp($sattr->getName(),$checkattr))
continue;
$formula = preg_replace("/$checkattr/",$sattr->getName(),$formula);
$matchall[1][$index] = $sattr->getName();
}
$elem_id = 0;
foreach ($matchall[0] as $index => $null) {
$match_attr = strtolower($matchall[1][$index]);
$match_subst = $matchall[2][$index];
$match_mod = $matchall[3][$index];
$match_delim = $matchall[4][$index];
$substrarray = array();
if (! isset($varcount[$match_attr]))
$varcount[$match_attr] = 0;
else
$varcount[$match_attr]++;
$js_match_attr = $match_attr;
$match_attr = $js_match_attr.'xx'.$varcount[$match_attr];
$formula = preg_replace('/%'.$js_match_attr.'([|\/%])/i','%'.$match_attr.'$1',$formula,1);
$attribute->js['autoFill'] .= sprintf(" var %s;\n",$match_attr);
$attribute->js['autoFill'] .= sprintf(
" var elem$elem_id = document.getElementById(pre+'%s'+suf);\n".
" if (!elem$elem_id) return;\n", $js_match_attr);
if (strstr($match_mod,'T')) {
$attribute->js['autoFill'] .= sprintf(" %s = elem$elem_id.options[elem$elem_id.selectedIndex].text;\n",
$match_attr);
} else {
$attribute->js['autoFill'] .= sprintf(" %s = elem$elem_id.value;\n",$match_attr);
}
$elem_id++;
if (strstr($match_mod,'k')) {
preg_match_all('/([0-9]+)/',trim($match_subst),$substrarray);
if (isset($substrarray[1][0])) {
$tok_idx = $substrarray[1][0];
} else {
$tok_idx = '0';
}
$attribute->js['autoFill'] .= sprintf(" %s = %s.split(':')[%s];\n",$match_attr,$match_attr,$tok_idx);
} elseif (strstr($match_mod,'K')) {
preg_match_all('/([0-9]+)/',trim($match_subst),$substrarray);
if (isset($substrarray[1][0])) {
$tok_idx = $substrarray[1][0];
} else {
$tok_idx = '0';
}
if ($match_delim == '') {
$delimiter = ' ';
} else {
$delimiter = preg_quote($match_delim);
}
$attribute->js['autoFill'] .= sprintf(" %s = %s.split('%s')[%s];\n",$match_attr,$match_attr,$delimiter,$tok_idx);
} else {
preg_match_all('/([0-9]*)-([0-9]*)/',trim($match_subst),$substrarray);
if ((isset($substrarray[1][0]) && $substrarray[1][0]) || (isset($substrarray[2][0]) && $substrarray[2][0])) {
$attribute->js['autoFill'] .= sprintf(" %s = %s.substr(%s,%s);\n",
$match_attr,$match_attr,
$substrarray[1][0] ? $substrarray[1][0] : '0',
$substrarray[2][0] ? $substrarray[2][0] : sprintf('%s.length',$match_attr));
}
}
if (strstr($match_mod,'l')) {
$attribute->js['autoFill'] .= sprintf(" %s = %s.toLowerCase();\n",$match_attr,$match_attr);
}
if (strstr($match_mod,'U')) {
$attribute->js['autoFill'] .= sprintf(" %s = %s.toUpperCase();\n",$match_attr,$match_attr);
}
if (strstr($match_mod,'A')) {
$attribute->js['autoFill'] .= sprintf(" %s = toAscii(%s);\n",$match_attr,$match_attr);
}
# Matchfor only entry without modifiers.
$formula = preg_replace('/^%('.$match_attr.')%$/U','$1 + \'\'',$formula);
# Matchfor only entry with modifiers.
$formula = preg_replace('/^%('.$match_attr.')(\|[0-9]*-[0-9]*)?(\/[KklTUA]+)?(?:\|(.))?%$/U','$1 + \'\'',$formula);
# Matchfor begining entry.
$formula = preg_replace('/^%('.$match_attr.')(\|[0-9]*-[0-9]*)?(\/[KklTUA]+)?(?:\|(.))?%/U','$1 + \'',$formula);
# Matchfor ending entry.
$formula = preg_replace('/%('.$match_attr.')(\|[0-9]*-[0-9]*)?(\/[KklTUA]+)?(?:\|(.))?%$/U','\' + $1 ',$formula);
# Match for entries not at begin/end.
$formula = preg_replace('/%('.$match_attr.')(\|[0-9]*-[0-9]*)?(\/[KklTUA]+)?(?:\|(.))?%/U','\' + $1 + \'',$formula);
$attribute->js['autoFill'] .= "\n";
}
$attribute->js['autoFill'] .= sprintf(" fillRec(pre+'%s'+suf, %s); // %s\n",strtolower($attr),$formula,$string);
$attribute->js['autoFill'] .= "\n";
} }
} }

View File

@ -29,7 +29,7 @@ class AjaxController extends Controller
'lazy'=>TRUE, 'lazy'=>TRUE,
'icon'=>'fa-fw fas fa-sitemap', 'icon'=>'fa-fw fas fa-sitemap',
'tooltip'=>$item->getDn(), 'tooltip'=>$item->getDn(),
]); ])->values();
} }
/** /**

View File

@ -8,7 +8,9 @@ use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
use App\Exceptions\InvalidUsage;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use App\Ldap\Entry;
class LoginController extends Controller class LoginController extends Controller
{ {
@ -51,6 +53,30 @@ class LoginController extends Controller
]; ];
} }
/**
* When attempt to login
*
* @param Request $request
* @return void
* @throws InvalidUsage
*/
public function attemptLogin(Request $request)
{
$attempt = $this->guard()->attempt(
$this->credentials($request), $request->boolean('remember')
);
// If the login failed, and PLA is set to use DN login, check if the entry exists.
// If the entry doesnt exist, it might be the root DN, which cannot be used to login
if ((! $attempt) && $request->dn && config('pla.login.alert_rootdn',TRUE)) {
$dn = config('server')->fetch($request->dn);
$o = new Entry;
if (! $dn && $o->getConnection()->getLdapConnection()->errNo() === 32)
abort(501,'Authentication set to DN, but the DN doesnt exist');
}
}
/** /**
* We need to delete our encrypted username/password cookies * We need to delete our encrypted username/password cookies
* *

View File

@ -6,6 +6,7 @@ use Illuminate\Contracts\View\View;
use Illuminate\View\Component; use Illuminate\View\Component;
use App\Classes\LDAP\Attribute as LDAPAttribute; use App\Classes\LDAP\Attribute as LDAPAttribute;
use App\Classes\Template;
class Attribute extends Component class Attribute extends Component
{ {
@ -14,12 +15,12 @@ class Attribute extends Component
public bool $new; public bool $new;
public bool $old; public bool $old;
public bool $updated; public bool $updated;
public bool $template; public ?Template $template;
/** /**
* Create a new component instance. * Create a new component instance.
*/ */
public function __construct(?LDAPAttribute $o,bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,bool $updated=FALSE,string $template=NULL) public function __construct(?LDAPAttribute $o,bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,bool $updated=FALSE,?Template $template=NULL)
{ {
$this->o = $o; $this->o = $o;
$this->edit = $edit; $this->edit = $edit;
@ -38,7 +39,12 @@ class Attribute extends Component
{ {
return $this->o return $this->o
? $this->o ? $this->o
->render(edit: $this->edit,old: $this->old,new: $this->new,template: $this->template,updated: $this->updated) ->render(
edit: $this->edit,
old: $this->old,
new: $this->new,
updated: $this->updated,
template: $this->template)
: __('Unknown'); : __('Unknown');
} }
} }

View File

@ -84,8 +84,12 @@ return [
* setup. * setup.
*/ */
'login' => [ 'login' => [
'attr' => [env('LDAP_LOGIN_ATTR','uid') => env('LDAP_LOGIN_ATTR_DESC','User ID')], // Attribute used to find user for login // Attribute used to find user for login
'objectclass' => explode(',',env('LDAP_LOGIN_OBJECTCLASS', 'posixAccount')), // Objectclass that users must contain to login 'attr' => [strtolower(env('LDAP_LOGIN_ATTR','uid')) => env('LDAP_LOGIN_ATTR_DESC','User ID')],
// Objectclass that users must contain to login
'objectclass' => explode(',',env('LDAP_LOGIN_OBJECTCLASS', 'posixAccount')),
// Alert if DN is being used, and the login fails, and the the DN doesnt exist
'alert_rootdn' => env('LDAP_ALERT_ROOTDN',TRUE) && strtolower(env('LDAP_LOGIN_ATTR','uid')) === 'dn',
], ],
'template' => [ 'template' => [

189
package-lock.json generated
View File

@ -53,9 +53,9 @@
} }
}, },
"node_modules/@babel/compat-data": { "node_modules/@babel/compat-data": {
"version": "7.27.3", "version": "7.27.5",
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.27.3.tgz", "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.27.5.tgz",
"integrity": "sha512-V42wFfx1ymFte+ecf6iXghnnP8kWTO+ZLXIyZq+1LAXHHvTZdVxicn4yiVYdYMGaCO3tmqub11AorKkv+iodqw==", "integrity": "sha512-KiRAp/VoJaWkkte84TvUd9qjdbZAdiqyvMxrGl1N6vzFogKmaLgoM3L1kgtLicp2HP5fBJS8JrZKLVIZGVJAVg==",
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
@ -101,12 +101,12 @@
} }
}, },
"node_modules/@babel/generator": { "node_modules/@babel/generator": {
"version": "7.27.3", "version": "7.27.5",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.3.tgz", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.5.tgz",
"integrity": "sha512-xnlJYj5zepml8NXtjkG0WquFUv8RskFqyFcVgTBp5k+NaA/8uw/K+OSVf8AMGw5e9HKP2ETd5xpK5MLZQD6b4Q==", "integrity": "sha512-ZGhA37l0e/g2s1Cnzdix0O3aLYm66eF8aufiVteOgnwxgnRP8GoyMj7VWsgWnQbVKXyge7hqrFh2K2TQM6t1Hw==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/parser": "^7.27.3", "@babel/parser": "^7.27.5",
"@babel/types": "^7.27.3", "@babel/types": "^7.27.3",
"@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/gen-mapping": "^0.3.5",
"@jridgewell/trace-mapping": "^0.3.25", "@jridgewell/trace-mapping": "^0.3.25",
@ -378,22 +378,22 @@
} }
}, },
"node_modules/@babel/helpers": { "node_modules/@babel/helpers": {
"version": "7.27.4", "version": "7.27.6",
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.4.tgz", "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.6.tgz",
"integrity": "sha512-Y+bO6U+I7ZKaM5G5rDUZiYfUvQPUibYmAFe7EnKdnKBbVXDZxvp+MWOH5gYciY0EPk4EScsuFMQBbEfpdRKSCQ==", "integrity": "sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/template": "^7.27.2", "@babel/template": "^7.27.2",
"@babel/types": "^7.27.3" "@babel/types": "^7.27.6"
}, },
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
} }
}, },
"node_modules/@babel/parser": { "node_modules/@babel/parser": {
"version": "7.27.4", "version": "7.27.5",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.4.tgz", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.5.tgz",
"integrity": "sha512-BRmLHGwpUqLFR2jzx9orBuX/ABDkj2jLKOXrHDTN2aOKL+jFDDKaRNo9nyYsIl9h/UE/7lMKdDjKQQyxKKDZ7g==", "integrity": "sha512-OsQd175SxWkGlzbny8J3K8TnnDD0N3lrIUtB92xwyRpzaenGZhxDvxN/JgU00U3CDZNj9tPuDJ5H0WS4Nt3vKg==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/types": "^7.27.3" "@babel/types": "^7.27.3"
@ -651,9 +651,9 @@
} }
}, },
"node_modules/@babel/plugin-transform-block-scoping": { "node_modules/@babel/plugin-transform-block-scoping": {
"version": "7.27.3", "version": "7.27.5",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.27.3.tgz", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.27.5.tgz",
"integrity": "sha512-+F8CnfhuLhwUACIJMLWnjz6zvzYM2r0yeIHKlbgfw7ml8rOMJsXNXV/hyRcb3nb493gRs4WvYpQAndWj/qQmkQ==", "integrity": "sha512-JF6uE2s67f0y2RZcm2kpAUEbD50vH62TyWVebxwHAlbSdM49VqPz8t4a1uIjp4NIOIZ4xzLfjY5emt/RCyC7TQ==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/helper-plugin-utils": "^7.27.1" "@babel/helper-plugin-utils": "^7.27.1"
@ -1189,9 +1189,9 @@
} }
}, },
"node_modules/@babel/plugin-transform-regenerator": { "node_modules/@babel/plugin-transform-regenerator": {
"version": "7.27.4", "version": "7.27.5",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.27.4.tgz", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.27.5.tgz",
"integrity": "sha512-Glp/0n8xuj+E1588otw5rjJkTXfzW7FjH3IIUrfqiZOPQCd2vbg8e+DQE8jK9g4V5/zrxFW+D9WM9gboRPELpQ==", "integrity": "sha512-uhB8yHerfe3MWnuLAhEbeQ4afVoqv8BQsPqrTv7e/jZ9y00kJL6l9a/f4OWaKxotmjzewfEyXE1vgDJenkQ2/Q==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/helper-plugin-utils": "^7.27.1" "@babel/helper-plugin-utils": "^7.27.1"
@ -1509,9 +1509,9 @@
} }
}, },
"node_modules/@babel/runtime": { "node_modules/@babel/runtime": {
"version": "7.27.4", "version": "7.27.6",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.4.tgz", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.6.tgz",
"integrity": "sha512-t3yaEOuGu9NlIZ+hIeGbBjFtZT7j2cb2tg0fuaJKeGotchRjjLfrBA9Kwf8quhpP1EUuxModQg04q/mBwyg8uA==", "integrity": "sha512-vbavdySgbTTrmFE+EsiqUTzlOr5bzlnJtUv9PynGCAKvfQqjIXbvFdumPM/GxMDfyuGMJaJAU6TO4zc1Jf1i8Q==",
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
@ -1550,9 +1550,9 @@
} }
}, },
"node_modules/@babel/types": { "node_modules/@babel/types": {
"version": "7.27.3", "version": "7.27.6",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.3.tgz", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.6.tgz",
"integrity": "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw==", "integrity": "sha512-ETyHEk2VHHvl9b9jZP5IHPavHYk57EhanlRRuae9XCpb/j5bDCbPPMOBfCWhnl/7EDJz0jEMCi/RhccCE8r1+Q==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/helper-string-parser": "^7.27.1", "@babel/helper-string-parser": "^7.27.1",
@ -2046,9 +2046,9 @@
} }
}, },
"node_modules/@types/body-parser": { "node_modules/@types/body-parser": {
"version": "1.19.5", "version": "1.19.6",
"resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz",
"integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@types/connect": "*", "@types/connect": "*",
@ -2114,15 +2114,15 @@
} }
}, },
"node_modules/@types/estree": { "node_modules/@types/estree": {
"version": "1.0.7", "version": "1.0.8",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
"integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==", "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/@types/express": { "node_modules/@types/express": {
"version": "4.17.22", "version": "4.17.23",
"resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.22.tgz", "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.23.tgz",
"integrity": "sha512-eZUmSnhRX9YRSkplpz0N+k6NljUUn5l3EWZIKZvYzhvMphEuNiyyy1viH/ejgt66JWgALwC/gtSUAeQKtSwW/w==", "integrity": "sha512-Crp6WY9aTYP3qPi2wGDo9iUe/rceX01UMhnF1jmwDcKCFM6cx7YhGP/Mpr3y9AASpfHixIG0E6azCcL5OcDHsQ==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@types/body-parser": "*", "@types/body-parser": "*",
@ -2166,9 +2166,9 @@
} }
}, },
"node_modules/@types/http-errors": { "node_modules/@types/http-errors": {
"version": "2.0.4", "version": "2.0.5",
"resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz",
"integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/@types/http-proxy": { "node_modules/@types/http-proxy": {
@ -2245,12 +2245,12 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/@types/node": { "node_modules/@types/node": {
"version": "22.15.29", "version": "24.0.3",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.29.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-24.0.3.tgz",
"integrity": "sha512-LNdjOkUDlU1RZb8e1kOIUpN1qQUlzGkEtbVNo53vbrwDg5om6oduhm4SiUaPW5ASTXhAiP0jInWG8Qx9fVlOeQ==", "integrity": "sha512-R4I/kzCYAdRLzfiCabn9hxWfbuHS573x+r0dJMkkzThEa7pbrcDWK+9zu3e7aBOouf+rQAciqPFMnxwr0aWgKg==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"undici-types": "~6.21.0" "undici-types": "~7.8.0"
} }
}, },
"node_modules/@types/node-forge": { "node_modules/@types/node-forge": {
@ -2287,9 +2287,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/@types/send": { "node_modules/@types/send": {
"version": "0.17.4", "version": "0.17.5",
"resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.5.tgz",
"integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", "integrity": "sha512-z6F2D3cOStZvuk2SaP6YrwkNO65iTZcwA2ZkSABegdkAh/lf+Aa/YQndZVfmEXT5vgAp6zv06VQ3ejSVjAny4w==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@types/mime": "^1", "@types/mime": "^1",
@ -2306,9 +2306,9 @@
} }
}, },
"node_modules/@types/serve-static": { "node_modules/@types/serve-static": {
"version": "1.15.7", "version": "1.15.8",
"resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.8.tgz",
"integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", "integrity": "sha512-roei0UY3LhpOJvjbIP6ZZFngyLKl5dskOtDhxY5THRSpO+ZI+nzJ+m5yUMzGrp89YRa7lvknKkMYjqQFGwA7Sg==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@types/http-errors": "*", "@types/http-errors": "*",
@ -2557,9 +2557,9 @@
} }
}, },
"node_modules/acorn": { "node_modules/acorn": {
"version": "8.14.1", "version": "8.15.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
"integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
"license": "MIT", "license": "MIT",
"bin": { "bin": {
"acorn": "bin/acorn" "acorn": "bin/acorn"
@ -2801,9 +2801,9 @@
} }
}, },
"node_modules/axios": { "node_modules/axios": {
"version": "1.9.0", "version": "1.10.0",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.9.0.tgz", "resolved": "https://registry.npmjs.org/axios/-/axios-1.10.0.tgz",
"integrity": "sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg==", "integrity": "sha512-/1xYAC4MP/HEG+3duIhFr4ZQXR4sQXOIe+o6sdqzeykGLx6Upp/1p8MHqhINOvGeP7xyNHe7tsiJByc4SSVUxw==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"follow-redirects": "^1.15.6", "follow-redirects": "^1.15.6",
@ -3020,9 +3020,9 @@
"license": "ISC" "license": "ISC"
}, },
"node_modules/bootstrap": { "node_modules/bootstrap": {
"version": "5.3.6", "version": "5.3.7",
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.6.tgz", "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.7.tgz",
"integrity": "sha512-jX0GAcRzvdwISuvArXn3m7KZscWWFAf1MKBcnzaN02qWMb3jpMoUX4/qgeiGzqyIb4ojulRzs89UCUmGcFSzTA==", "integrity": "sha512-7KgiD8UHjfcPBHEpDNg+zGz8L3LqR3GVwqZiBRFX04a1BCArZOz1r2kjly2HQ0WokqTO0v1nF+QAt8dsW4lKlw==",
"funding": [ "funding": [
{ {
"type": "github", "type": "github",
@ -3055,9 +3055,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/brace-expansion": { "node_modules/brace-expansion": {
"version": "1.1.11", "version": "1.1.12",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"balanced-match": "^1.0.0", "balanced-match": "^1.0.0",
@ -3312,9 +3312,9 @@
} }
}, },
"node_modules/caniuse-lite": { "node_modules/caniuse-lite": {
"version": "1.0.30001720", "version": "1.0.30001723",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001720.tgz", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001723.tgz",
"integrity": "sha512-Ec/2yV2nNPwb4DnTANEV99ZWwm3ZWfdlfkQbWSDDt+PsXEVYwlhPH8tdMaPunYTKKmz7AnHi2oNEi1GcmKCD8g==", "integrity": "sha512-1R/elMjtehrFejxwmexeXAtae5UO9iSyFn6G/I806CYC/BLyyBk1EPhrKBkWhy6wM6Xnm47dSJQec+tLJ39WHw==",
"funding": [ "funding": [
{ {
"type": "opencollective", "type": "opencollective",
@ -3674,12 +3674,12 @@
} }
}, },
"node_modules/core-js-compat": { "node_modules/core-js-compat": {
"version": "3.42.0", "version": "3.43.0",
"resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.42.0.tgz", "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.43.0.tgz",
"integrity": "sha512-bQasjMfyDGyaeWKBIu33lHh9qlSR0MFE/Nmc6nMjf/iU9b3rSMdAYz1Baxrv4lPdGUsTqZudHA4jIGSJy0SWZQ==", "integrity": "sha512-2GML2ZsCc5LR7hZYz4AXmjQw8zuy2T//2QntwdnpuYI7jteT6GVYJL7F6C2C57R7gSYrcqVW3lAALefdbhBLDA==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"browserslist": "^4.24.4" "browserslist": "^4.25.0"
}, },
"funding": { "funding": {
"type": "opencollective", "type": "opencollective",
@ -4325,9 +4325,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/electron-to-chromium": { "node_modules/electron-to-chromium": {
"version": "1.5.161", "version": "1.5.170",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.161.tgz", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.170.tgz",
"integrity": "sha512-hwtetwfKNZo/UlwHIVBlKZVdy7o8bIZxxKs0Mv/ROPiQQQmDgdm5a+KvKtBsxM8ZjFzTaCeLoodZ8jiBE3o9rA==", "integrity": "sha512-GP+M7aeluQo9uAyiTCxgIj/j+PrWhMlY7LFVj8prlsPljd0Fdg9AprlfUi+OCSFWy9Y5/2D/Jrj9HS8Z4rpKWA==",
"license": "ISC" "license": "ISC"
}, },
"node_modules/elliptic": { "node_modules/elliptic": {
@ -4909,14 +4909,15 @@
} }
}, },
"node_modules/form-data": { "node_modules/form-data": {
"version": "4.0.2", "version": "4.0.3",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.3.tgz",
"integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==", "integrity": "sha512-qsITQPfmvMOSAdeyZ+12I1c+CKSstAFAwu+97zrnWAbIr5u8wfsExUzCesVLC8NgHuRUqNN4Zy6UPWUTRGslcA==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"asynckit": "^0.4.0", "asynckit": "^0.4.0",
"combined-stream": "^1.0.8", "combined-stream": "^1.0.8",
"es-set-tostringtag": "^2.1.0", "es-set-tostringtag": "^2.1.0",
"hasown": "^2.0.2",
"mime-types": "^2.1.12" "mime-types": "^2.1.12"
}, },
"engines": { "engines": {
@ -5631,9 +5632,9 @@
} }
}, },
"node_modules/immutable": { "node_modules/immutable": {
"version": "5.1.2", "version": "5.1.3",
"resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.2.tgz", "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.3.tgz",
"integrity": "sha512-qHKXW1q6liAk1Oys6umoaZbDRqjcjgSrbnrifHsfsttza7zcvRAsL7mMV6xWcyhwQy7Xj5v4hhbr6b+iDYwlmQ==", "integrity": "sha512-+chQdDfvscSF1SJqv2gn4SRO2ZyS3xL3r7IW/wWEEzrzLisnOlKiQu5ytC/BVNcS15C39WT2Hg/bjKjDMcu+zg==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/import-fresh": { "node_modules/import-fresh": {
@ -7117,9 +7118,9 @@
} }
}, },
"node_modules/postcss": { "node_modules/postcss": {
"version": "8.5.4", "version": "8.5.6",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.4.tgz", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz",
"integrity": "sha512-QSa9EBe+uwlGTFmHsPKokv3B/oEMQZxfqW0QqNCyhpa6mB1afzulwn8hihglqAb2pOw+BJgNlmXQ8la2VeHB7w==", "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==",
"funding": [ "funding": [
{ {
"type": "opencollective", "type": "opencollective",
@ -8222,9 +8223,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/sass": { "node_modules/sass": {
"version": "1.89.1", "version": "1.89.2",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.89.1.tgz", "resolved": "https://registry.npmjs.org/sass/-/sass-1.89.2.tgz",
"integrity": "sha512-eMLLkl+qz7tx/0cJ9wI+w09GQ2zodTkcE/aVfywwdlRcI3EO19xGnbmJwg/JMIm+5MxVJ6outddLZ4Von4E++Q==", "integrity": "sha512-xCmtksBKd/jdJ9Bt9p7nPKiuqrlBMBuuGkQlkhZjjQk3Ty48lv93k5Dq6OPkKt4XwxDJ7tvlfrTa1MPA9bf+QA==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"chokidar": "^4.0.0", "chokidar": "^4.0.0",
@ -8604,9 +8605,9 @@
} }
}, },
"node_modules/shell-quote": { "node_modules/shell-quote": {
"version": "1.8.2", "version": "1.8.3",
"resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.2.tgz", "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.3.tgz",
"integrity": "sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA==", "integrity": "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==",
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">= 0.4" "node": ">= 0.4"
@ -8995,9 +8996,9 @@
} }
}, },
"node_modules/terser": { "node_modules/terser": {
"version": "5.40.0", "version": "5.43.0",
"resolved": "https://registry.npmjs.org/terser/-/terser-5.40.0.tgz", "resolved": "https://registry.npmjs.org/terser/-/terser-5.43.0.tgz",
"integrity": "sha512-cfeKl/jjwSR5ar7d0FGmave9hFGJT8obyo0z+CrQOylLDbk7X81nPU6vq9VORa5jU30SkDnT2FXjLbR8HLP+xA==", "integrity": "sha512-CqNNxKSGKSZCunSvwKLTs8u8sGGlp27sxNZ4quGh0QeNuyHM0JSEM/clM9Mf4zUp6J+tO2gUXhgXT2YMMkwfKQ==",
"license": "BSD-2-Clause", "license": "BSD-2-Clause",
"dependencies": { "dependencies": {
"@jridgewell/source-map": "^0.3.3", "@jridgewell/source-map": "^0.3.3",
@ -9176,9 +9177,9 @@
} }
}, },
"node_modules/undici-types": { "node_modules/undici-types": {
"version": "6.21.0", "version": "7.8.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.8.0.tgz",
"integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", "integrity": "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/unicode-canonical-property-names-ecmascript": { "node_modules/unicode-canonical-property-names-ecmascript": {
@ -9790,9 +9791,9 @@
} }
}, },
"node_modules/webpack/node_modules/webpack-sources": { "node_modules/webpack/node_modules/webpack-sources": {
"version": "3.3.0", "version": "3.3.2",
"resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.0.tgz", "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.2.tgz",
"integrity": "sha512-77R0RDmJfj9dyv5p3bM5pOHa+X8/ZkO9c7kpDstigkC4nIDobadsfSGCwB4bKhMVxqAok8tajaoR8rirM7+VFQ==", "integrity": "sha512-ykKKus8lqlgXX/1WjudpIEjqsafjOTcOJqxnAbMLAu/KCsDCJ6GBtvscewvTkrn24HsnvFwrSCbenFrhtcCsAA==",
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=10.13.0" "node": ">=10.13.0"

View File

@ -37,10 +37,10 @@ function getNode(item) {
$('.main-content').empty().append(e.responseText); $('.main-content').empty().append(e.responseText);
break; break;
case 409: // Not in root case 409: // Not in root
location.replace('/#'+item);
break;
case 419: // Session Expired case 419: // Session Expired
location.replace('/#'+item); location.replace('/#'+item);
// When the session expires, and we are in the tree, we need to force a reload
if (location.pathname === '/')
location.reload(); location.reload();
break; break;
case 500: case 500:

View File

@ -169,6 +169,9 @@
$('button[id^="link-"]').on('click',function(item) { $('button[id^="link-"]').on('click',function(item) {
var content; var content;
// Remove our fancy-tree highlight, since we are rendering the frame
$('.fancytree-node.fancytree-active').removeClass('fancytree-active');
$.ajax({ $.ajax({
url: $(this).data('link'), url: $(this).data('link'),
method: 'GET', method: 'GET',

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="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

@ -0,0 +1,33 @@
@extends('architect::layouts.error')
@section('error')
501: @lang('LDAP Authentication Error')
@endsection
@section('content')
<table class="table table-sm table-borderless table-condensed">
<tr>
<th>@lang('Error')</th>
</tr>
<tr>
<td colspan="2">{{ $exception->getMessage() }}</td>
</tr>
<tr>
<th>@lang('Possible Causes')</th>
</tr>
<tr>
<td>
<ul class="ps-3">
<li>The DN you used to login actually doesnt exist in the server (DN's must exist in order to login)</li>
<li>You are attempting to use the <strong>rootdn</strong> to login (not supported)</li>
</ul>
</td>
</tr>
</table>
<p>To suppress this message, set <strong>LDAP_ALERT_ROOTDN</strong> to <strong>FALSE</strong> before starting PLA.</p>
<p>Back to <a href="{{ url('login') }}">login</a>?</p>
@endsection

View File

@ -9,7 +9,7 @@
@php($up=(session()->pull('updated') ?: collect())) @php($up=(session()->pull('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->name" :updated="$up->contains($ao->name_lc)"/> <x-attribute-type :o="$ao" :edit="TRUE" :new="FALSE" :template="$template" :updated="$up->contains($ao->name_lc)"/>
@endforeach @endforeach
</div> </div>
</div> </div>

View File

@ -66,7 +66,7 @@
<x-attribute-type :o="$o->getObject('rdn')" :edit="TRUE" :new="FALSE" :updated="FALSE"/> <x-attribute-type :o="$o->getObject('rdn')" :edit="TRUE" :new="FALSE" :updated="FALSE"/>
@foreach($o->getVisibleAttributes() as $ao) @foreach($o->getVisibleAttributes() as $ao)
<x-attribute-type :o="$ao" :edit="TRUE" :new="FALSE" :updated="FALSE"/> <x-attribute-type :o="$ao" :edit="TRUE" :new="FALSE" :template="$template" :updated="FALSE"/>
@endforeach @endforeach
@if(! $template) @if(! $template)

View File

@ -75,8 +75,8 @@
<div class="d-flex justify-content-center"> <div class="d-flex justify-content-center">
<div role="group" class="btn-group btn-group-sm nav pb-3"> <div role="group" class="btn-group btn-group-sm nav pb-3">
<!-- If we have templates that cover this entry --> <!-- If we have templates that cover this entry -->
@foreach($o->templates as $template => $name) @foreach($o->templates as $template)
<span data-bs-toggle="tab" href="#template-{{$template}}" @class(['btn','btn-outline-focus','active'=>$loop->index === 0])><i class="fa fa-fw pe-2 {{ $o->template($template)->icon }}"></i> {{ $name }}</span> <span data-bs-toggle="tab" href="#template-{{ $template->name }}" @class(['btn','btn-outline-focus','active'=>$loop->index === 0])><i class="fa fa-fw pe-2 {{ $template->icon }}"></i> {{ $template->title }}</span>
@endforeach @endforeach
@if($o->templates->count()) @if($o->templates->count())
<span data-bs-toggle="tab" href="#template-default" @class(['btn','btn-outline-focus','p-1','active'=>(! $o->templates->count())])>{{ __('LDAP Entry') }}</span> <span data-bs-toggle="tab" href="#template-default" @class(['btn','btn-outline-focus','p-1','active'=>(! $o->templates->count())])>{{ __('LDAP Entry') }}</span>
@ -85,9 +85,9 @@
</div> </div>
<div class="tab-content"> <div class="tab-content">
@foreach($o->templates as $template => $name) @foreach($o->templates as $template)
<div @class(['tab-pane','active'=>$loop->index === 0]) id="template-{{$template}}" role="tabpanel"> <div @class(['tab-pane','active'=>$loop->index === 0]) id="template-{{ $template->name }}" role="tabpanel">
@include('fragment.template.dn',['template'=>$o->template($template)]) @include('fragment.template.dn',['template'=>$template])
</div> </div>
@endforeach @endforeach