Compare commits
20 Commits
Author | SHA1 | Date | |
---|---|---|---|
c2ee9064eb | |||
c6e1640752 | |||
917a3c1a0d | |||
148d19bbce | |||
6c501cc29d | |||
2ce0ed8974 | |||
9a6d80986a | |||
fa989b8f10 | |||
4e991db8b1 | |||
181971acc4 | |||
3493504720 | |||
54f27d3d16 | |||
3c0eb876e4 | |||
6d55b52cd4 | |||
16a1f85a79 | |||
f8d7819153 | |||
75dbb37d8b | |||
309fe83c98 | |||
ffb98631a6 | |||
be69e22867 |
43
.env.testing
43
.env.testing
@@ -1,50 +1,17 @@
|
||||
APP_NAME=Laravel
|
||||
APP_ENV=dev
|
||||
APP_KEY=base64:KvIecx8zoy6RjcbJM8s98ZKs9IDGUHFVqBRn3Awfmso=
|
||||
APP_ENV=local
|
||||
APP_KEY=
|
||||
APP_DEBUG=true
|
||||
APP_URL=http://localhost
|
||||
|
||||
LOG_CHANNEL=stack
|
||||
LOG_CHANNEL=stderr
|
||||
|
||||
DB_CONNECTION=mysql
|
||||
DB_HOST=127.0.0.1
|
||||
DB_PORT=3306
|
||||
DB_DATABASE=homestead
|
||||
DB_USERNAME=homestead
|
||||
DB_PASSWORD=secret
|
||||
|
||||
BROADCAST_DRIVER=log
|
||||
CACHE_DRIVER=file
|
||||
CACHE_DRIVER=array
|
||||
QUEUE_CONNECTION=sync
|
||||
SESSION_DRIVER=file
|
||||
SESSION_LIFETIME=120
|
||||
|
||||
REDIS_HOST=127.0.0.1
|
||||
REDIS_PASSWORD=null
|
||||
REDIS_PORT=6379
|
||||
|
||||
MAIL_DRIVER=smtp
|
||||
MAIL_HOST=smtp.mailtrap.io
|
||||
MAIL_PORT=2525
|
||||
MAIL_USERNAME=null
|
||||
MAIL_PASSWORD=null
|
||||
MAIL_ENCRYPTION=null
|
||||
|
||||
AWS_ACCESS_KEY_ID=
|
||||
AWS_SECRET_ACCESS_KEY=
|
||||
AWS_DEFAULT_REGION=us-east-1
|
||||
AWS_BUCKET=
|
||||
|
||||
PUSHER_APP_ID=
|
||||
PUSHER_APP_KEY=
|
||||
PUSHER_APP_SECRET=
|
||||
PUSHER_APP_CLUSTER=mt1
|
||||
|
||||
MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
|
||||
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
|
||||
|
||||
LDAP_HOST=test_ldap
|
||||
LDAP_PORT=389
|
||||
LDAP_HOST=openldap
|
||||
LDAP_BASE_DN="dc=Test"
|
||||
LDAP_USERNAME="cn=admin,dc=Test"
|
||||
LDAP_PASSWORD="test"
|
||||
|
@@ -3,7 +3,7 @@ run-name: ${{ gitea.actor }} Building Docker Image 🐳
|
||||
on: [push]
|
||||
env:
|
||||
DOCKER_HOST: tcp://127.0.0.1:2375
|
||||
ASSETS: c2780a3
|
||||
ASSETS: 10eca55
|
||||
|
||||
jobs:
|
||||
test:
|
||||
|
@@ -38,6 +38,7 @@ The update to v2 is progressing well - here is a list of work to do and done:
|
||||
- [X] Support different password hash options
|
||||
- [X] Validate password is correct
|
||||
- [ ] JpegPhoto Create/Delete
|
||||
- [ ] Binary attribute upload
|
||||
- [X] JpegPhoto Display
|
||||
- [X] ObjectClass Add/Remove
|
||||
- [X] Add additional required attributes (for ObjectClass Addition)
|
||||
@@ -53,7 +54,7 @@ The update to v2 is progressing well - here is a list of work to do and done:
|
||||
- [X] Export entries as an LDAP
|
||||
- [X] Import LDIF
|
||||
- [X] Schema Browser
|
||||
- [ ] Searching
|
||||
- [X] Searching
|
||||
- [ ] Enforcing attribute uniqueness
|
||||
- [ ] Is there something missing?
|
||||
|
||||
|
@@ -106,11 +106,17 @@ class Attribute implements \Countable, \ArrayAccess
|
||||
$this->_values = collect($values);
|
||||
$this->_values_old = collect($values);
|
||||
|
||||
$this->oc = collect($oc);
|
||||
|
||||
$this->schema = (new Server)
|
||||
$this->schema = config('server')
|
||||
->schema('attributetypes',$name);
|
||||
|
||||
$this->oc = collect();
|
||||
|
||||
// Get the objectclass heirarchy for required attribute determination
|
||||
foreach ($oc as $objectclass) {
|
||||
$this->oc->push($objectclass);
|
||||
$this->oc = $this->oc->merge(config('server')->schema('objectclasses',$objectclass)->getParents()->pluck('name'));
|
||||
}
|
||||
|
||||
/*
|
||||
# Should this attribute be hidden
|
||||
if ($server->isAttrHidden($this->name))
|
||||
@@ -161,7 +167,7 @@ class Attribute implements \Countable, \ArrayAccess
|
||||
// The current attribute values
|
||||
'values' => ($this->no_attr_tags || $this->is_internal) ? $this->tagValues() : $this->_values,
|
||||
// The original attribute values
|
||||
'values_old' => $this->no_attr_tags ? $this->tagValuesOld() : $this->_values_old,
|
||||
'values_old' => ($this->no_attr_tags || $this->is_internal) ? $this->tagValuesOld() : $this->_values_old,
|
||||
|
||||
default => throw new \Exception('Unknown key:' . $key),
|
||||
};
|
||||
@@ -338,6 +344,12 @@ class Attribute implements \Countable, \ArrayAccess
|
||||
->with('updated',$updated);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the value of the original old values
|
||||
*
|
||||
* @param string $dotkey
|
||||
* @return string|null
|
||||
*/
|
||||
public function render_item_old(string $dotkey): ?string
|
||||
{
|
||||
return match ($this->schema->syntax_oid) {
|
||||
@@ -348,6 +360,12 @@ class Attribute implements \Countable, \ArrayAccess
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the value of the new values, which would include any pending udpates
|
||||
*
|
||||
* @param string $dotkey
|
||||
* @return string|null
|
||||
*/
|
||||
public function render_item_new(string $dotkey): ?string
|
||||
{
|
||||
return Arr::get($this->values->dot(),$dotkey);
|
||||
@@ -366,6 +384,12 @@ class Attribute implements \Countable, \ArrayAccess
|
||||
: collect();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the new values for this attribute, which would include any pending updates
|
||||
*
|
||||
* @param string $tag
|
||||
* @return Collection
|
||||
*/
|
||||
public function tagValues(string $tag=Entry::TAG_NOTAG): Collection
|
||||
{
|
||||
return collect($this->_values
|
||||
@@ -373,6 +397,12 @@ class Attribute implements \Countable, \ArrayAccess
|
||||
->get($tag,[]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the original values for this attribute, as stored in the LDAP server
|
||||
*
|
||||
* @param string $tag
|
||||
* @return Collection
|
||||
*/
|
||||
public function tagValuesOld(string $tag=Entry::TAG_NOTAG): Collection
|
||||
{
|
||||
return collect($this->_values_old
|
||||
|
@@ -18,6 +18,7 @@ final class Password extends Attribute
|
||||
use MD5Updates;
|
||||
|
||||
protected(set) bool $no_attr_tags = TRUE;
|
||||
protected(set) int $max_values_count = 1;
|
||||
|
||||
private const password_helpers = 'Classes/LDAP/Attribute/Password';
|
||||
public const commands = 'App\\Classes\\LDAP\\Attribute\\Password\\';
|
||||
|
@@ -10,16 +10,16 @@ final class Argon2i extends Base
|
||||
|
||||
public static function subid(string $password): bool
|
||||
{
|
||||
return str_starts_with(base64_decode(self::password($password)),self::identifier.'$');
|
||||
return str_starts_with(self::password($password),self::identifier.'$');
|
||||
}
|
||||
|
||||
public function compare(string $source,string $compare): bool
|
||||
{
|
||||
return password_verify($compare,base64_decode($this->password($source)));
|
||||
return password_verify($compare,$this->password($source));
|
||||
}
|
||||
|
||||
public function encode(string $password): string
|
||||
{
|
||||
return sprintf('{%s}%s',self::key,base64_encode(password_hash($password,PASSWORD_ARGON2I)));
|
||||
return sprintf('{%s}%s',self::key,password_hash($password,PASSWORD_ARGON2I));
|
||||
}
|
||||
}
|
@@ -3,6 +3,7 @@
|
||||
namespace App\Classes\LDAP;
|
||||
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use LdapRecord\LdapRecordException;
|
||||
|
||||
use App\Exceptions\Import\GeneralException;
|
||||
@@ -16,6 +17,8 @@ use App\Ldap\Entry;
|
||||
*/
|
||||
abstract class Import
|
||||
{
|
||||
private const LOGKEY = 'aI-';
|
||||
|
||||
// Valid LDIF commands
|
||||
protected const LDAP_IMPORT_ADD = 1;
|
||||
protected const LDAP_IMPORT_DELETE = 2;
|
||||
@@ -57,6 +60,8 @@ abstract class Import
|
||||
$o->save();
|
||||
|
||||
} catch (LdapRecordException $e) {
|
||||
Log::error(sprintf('%s:Import Commit Error',self::LOGKEY),['e'=>$e->getMessage(),'detailed'=>$e->getDetailedError()]);
|
||||
|
||||
if ($e->getDetailedError())
|
||||
return collect([
|
||||
'dn'=>$o->getDN(),
|
||||
@@ -76,6 +81,8 @@ abstract class Import
|
||||
]);
|
||||
}
|
||||
|
||||
Log::debug(sprintf('%s:Import Commited',self::LOGKEY));
|
||||
|
||||
return collect(['dn'=>$o->getDN(),'result'=>__('Created')]);
|
||||
|
||||
default:
|
||||
|
@@ -35,7 +35,7 @@ class LDIF extends Import
|
||||
// @todo When renaming DNs, the hotlink should point to the new entry on success, or the old entry on failure.
|
||||
foreach (preg_split('/(\r?\n|\r)/',$this->input) as $line) {
|
||||
$c++;
|
||||
Log::debug(sprintf('%s: LDIF Line [%s]',self::LOGKEY,$line));
|
||||
Log::debug(sprintf('%s:LDIF Line [%s]',self::LOGKEY,$line));
|
||||
$line = trim($line);
|
||||
|
||||
// If the line starts with a comment, ignore it
|
||||
@@ -48,7 +48,7 @@ class LDIF extends Import
|
||||
// Add the last attribute;
|
||||
$o->addAttributeItem($attribute,$base64encoded ? base64_decode($value) : $value);
|
||||
|
||||
Log::debug(sprintf('%s: Committing Entry [%s]',self::LOGKEY,$o->getDN()));
|
||||
Log::debug(sprintf('%s:- Committing Entry [%s]',self::LOGKEY,$o->getDN()));
|
||||
|
||||
// Commit
|
||||
$result->push($this->commit($o,$action));
|
||||
@@ -95,7 +95,7 @@ class LDIF extends Import
|
||||
// If $m is NULL, then this is the 2nd (or more) line of a base64 encoded value
|
||||
if (! $m) {
|
||||
$value .= $line;
|
||||
Log::debug(sprintf('%s: Attribute [%s] adding [%s] (%d)',self::LOGKEY,$attribute,$line,$c));
|
||||
Log::debug(sprintf('%s:- Attribute [%s] adding [%s] (%d)',self::LOGKEY,$attribute,$line,$c));
|
||||
|
||||
// add to last attr value
|
||||
continue 2;
|
||||
@@ -108,7 +108,7 @@ class LDIF extends Import
|
||||
throw new GeneralException(sprintf('Previous Entry not complete? (line %d)',$c));
|
||||
|
||||
$dn = $base64encoded ? base64_decode($value) : $value;
|
||||
Log::debug(sprintf('%s: Creating new entry:',self::LOGKEY,$dn));
|
||||
Log::debug(sprintf('%s:Creating new entry:',self::LOGKEY,$dn));
|
||||
//$o = Entry::find($dn);
|
||||
|
||||
// If it doesnt exist, we'll create it
|
||||
@@ -120,7 +120,7 @@ class LDIF extends Import
|
||||
$action = self::LDAP_IMPORT_ADD;
|
||||
|
||||
} else {
|
||||
Log::debug(sprintf('%s: Adding Attribute [%s] value [%s] (%d)',self::LOGKEY,$attribute,$value,$c));
|
||||
Log::debug(sprintf('%s:Adding Attribute [%s] value [%s] (%d)',self::LOGKEY,$attribute,$value,$c));
|
||||
|
||||
if ($value)
|
||||
$o->addAttributeItem($attribute,$base64encoded ? base64_decode($value) : $value);
|
||||
@@ -134,7 +134,7 @@ class LDIF extends Import
|
||||
$attribute = $m[1];
|
||||
$value = $m[3];
|
||||
|
||||
Log::debug(sprintf('%s: New Attribute [%s] with [%s] (%d)',self::LOGKEY,$attribute,$value,$c));
|
||||
Log::debug(sprintf('%s:- New Attribute [%s] with [%s] (%d)',self::LOGKEY,$attribute,$value,$c));
|
||||
}
|
||||
|
||||
if ($version !== 1)
|
||||
@@ -146,7 +146,7 @@ class LDIF extends Import
|
||||
// Add the last attribute;
|
||||
$o->addAttributeItem($attribute,$base64encoded ? base64_decode($value) : $value);
|
||||
|
||||
Log::debug(sprintf('%s: Committing Entry [%s]',self::LOGKEY,$o->getDN()));
|
||||
Log::debug(sprintf('%s:- Committing Entry [%s]',self::LOGKEY,$o->getDN()));
|
||||
|
||||
// Commit
|
||||
$result->push($this->commit($o,$action));
|
||||
|
@@ -204,7 +204,7 @@ final class Server
|
||||
default => TRUE,
|
||||
};
|
||||
|
||||
Log::debug(sprintf('%s:%s - %s',self::LOGKEY,$cache ? 'Caching' : 'Not Cached',$dn));
|
||||
Log::debug(sprintf('%s:%s - %s',self::LOGKEY,$cache ? 'DN CACHEABLE' : 'DN NOT cacheable',$dn));
|
||||
return $cache;
|
||||
}
|
||||
|
||||
@@ -216,7 +216,7 @@ final class Server
|
||||
private static function cachetime(): Carbon
|
||||
{
|
||||
return Carbon::now()
|
||||
->addSeconds(Config::get('ldap.cache.time'));
|
||||
->addSeconds(Config::get('ldap.cache.time') ?: 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -232,7 +232,8 @@ final class Server
|
||||
->setDN($dn)
|
||||
->cache(
|
||||
until: self::cachetime(),
|
||||
flush: self::cacheflush($dn))
|
||||
flush: self::cacheflush($dn)
|
||||
)
|
||||
->select($attrs);
|
||||
}
|
||||
|
||||
|
@@ -8,6 +8,7 @@ use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Crypt;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Redirect;
|
||||
use LdapRecord\Exceptions\InsufficientAccessException;
|
||||
use LdapRecord\LdapRecordException;
|
||||
@@ -114,7 +115,7 @@ class HomeController extends Controller
|
||||
$o = new Entry;
|
||||
$o->setDn($dn);
|
||||
|
||||
foreach ($request->except(['_token','key','step','rdn','rdn_value']) as $key => $value)
|
||||
foreach ($request->except(['_token','key','step','rdn','rdn_value','userpassword_hash']) as $key => $value)
|
||||
$o->{$key} = array_filter($value);
|
||||
|
||||
try {
|
||||
@@ -127,7 +128,7 @@ class HomeController extends Controller
|
||||
case 50:
|
||||
return Redirect::to('/')
|
||||
->withInput()
|
||||
->withErrors(sprintf('%s: %s (%s)',__('LDAP Server Error Code'),$x,__($e->getDetailedError()->getErrorMessage())));
|
||||
->with('failed',sprintf('%s: %s (%s)',__('LDAP Server Error Code'),$x,__($e->getDetailedError()->getErrorMessage())));
|
||||
|
||||
default:
|
||||
abort(599,$e->getDetailedError()->getErrorMessage());
|
||||
@@ -135,14 +136,14 @@ class HomeController extends Controller
|
||||
|
||||
// @todo when we create an entry, and it already exists, enable a redirect to it
|
||||
} catch (LdapRecordException $e) {
|
||||
return Redirect::back()
|
||||
->withInput()
|
||||
->withErrors(sprintf('%s: %s - %s: %s',
|
||||
__('LDAP Server Error Code'),
|
||||
$e->getDetailedError()->getErrorCode(),
|
||||
__($e->getDetailedError()->getErrorMessage()),
|
||||
$e->getDetailedError()->getDiagnosticMessage(),
|
||||
));
|
||||
return Redirect::back()
|
||||
->withInput()
|
||||
->with('failed',sprintf('%s: %s - %s: %s',
|
||||
__('LDAP Server Error Code'),
|
||||
$e->getDetailedError()->getErrorCode(),
|
||||
__($e->getDetailedError()->getErrorMessage()),
|
||||
$e->getDetailedError()->getDiagnosticMessage(),
|
||||
));
|
||||
}
|
||||
|
||||
return Redirect::to('/')
|
||||
@@ -165,7 +166,7 @@ class HomeController extends Controller
|
||||
case 50:
|
||||
return Redirect::to('/')
|
||||
->withInput()
|
||||
->withErrors(sprintf('%s: %s (%s)',__('LDAP Server Error Code'),$x,__($e->getDetailedError()->getErrorMessage())));
|
||||
->with('failed',sprintf('%s: %s (%s)',__('LDAP Server Error Code'),$x,__($e->getDetailedError()->getErrorMessage())));
|
||||
|
||||
default:
|
||||
abort(599,$e->getDetailedError()->getErrorMessage());
|
||||
@@ -178,7 +179,7 @@ class HomeController extends Controller
|
||||
case 8:
|
||||
return Redirect::to('/')
|
||||
->withInput()
|
||||
->withErrors(sprintf('%s: %s (%s)',__('LDAP Server Error Code'),$x,__($e->getDetailedError()->getErrorMessage())));
|
||||
->with('failed',sprintf('%s: %s (%s)',__('LDAP Server Error Code'),$x,__($e->getDetailedError()->getErrorMessage())));
|
||||
|
||||
default:
|
||||
abort(599,$e->getDetailedError()->getErrorMessage());
|
||||
@@ -335,21 +336,21 @@ class HomeController extends Controller
|
||||
case 50:
|
||||
return Redirect::to('/')
|
||||
->withInput()
|
||||
->withErrors(sprintf('%s: %s (%s)',__('LDAP Server Error Code'),$x,__($e->getDetailedError()->getErrorMessage())));
|
||||
->with('failed',sprintf('%s: %s (%s)',__('LDAP Server Error Code'),$x,__($e->getDetailedError()->getErrorMessage())));
|
||||
|
||||
default:
|
||||
abort(599,$e->getDetailedError()->getErrorMessage());
|
||||
}
|
||||
|
||||
} catch (LdapRecordException $e) {
|
||||
return Redirect::to('/')
|
||||
->withInput()
|
||||
->withErrors(sprintf('%s: %s - %s: %s',
|
||||
__('LDAP Server Error Code'),
|
||||
$e->getDetailedError()->getErrorCode(),
|
||||
__($e->getDetailedError()->getErrorMessage()),
|
||||
$e->getDetailedError()->getDiagnosticMessage(),
|
||||
));
|
||||
return Redirect::to('/')
|
||||
->withInput()
|
||||
->with('failed',sprintf('%s: %s - %s: %s',
|
||||
__('LDAP Server Error Code'),
|
||||
$e->getDetailedError()->getErrorCode(),
|
||||
__($e->getDetailedError()->getErrorMessage()),
|
||||
$e->getDetailedError()->getDiagnosticMessage(),
|
||||
));
|
||||
}
|
||||
|
||||
return Redirect::to('/')
|
||||
@@ -435,6 +436,7 @@ class HomeController extends Controller
|
||||
switch ($type) {
|
||||
case 'ldif':
|
||||
$import = new LDIFImport($x=($request->text ?: $request->file->get()));
|
||||
Log::debug('Processing LDIF import',['data'=>$x,'import'=>$import]);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
59
app/Http/Controllers/SearchController.php
Normal file
59
app/Http/Controllers/SearchController.php
Normal file
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Crypt;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
use App\Ldap\Entry;
|
||||
|
||||
class SearchController extends Controller
|
||||
{
|
||||
public function search(Request $request): Collection
|
||||
{
|
||||
$so = config('server');
|
||||
|
||||
// We are searching for a value
|
||||
if (strpos($request->term,'=')) {
|
||||
list($attr,$value) = explode('=',$request->term,2);
|
||||
$value = trim($value);
|
||||
|
||||
$result = collect();
|
||||
|
||||
foreach ($so->baseDNs() as $base) {
|
||||
$search = (new Entry)
|
||||
->in($base);
|
||||
|
||||
$search = ($x=Str::startsWith($value,'*'))
|
||||
? $search->whereEndsWith($attr,substr($value,1))
|
||||
: $search->whereStartsWith($attr,$value);
|
||||
|
||||
$result = $result->merge($search->get());
|
||||
}
|
||||
|
||||
return $result
|
||||
->map(fn($item)=>[
|
||||
'name'=>$item->getDN(),
|
||||
'value'=>Crypt::encryptString($item->getDN()),
|
||||
'category'=>sprintf('%s: [%s=%s%s]',__('Result'),$attr,$value,($x ? '' : '*'))
|
||||
]);
|
||||
|
||||
// We are searching for an attribute
|
||||
} else {
|
||||
$attrs = $so
|
||||
->schema('attributetypes')
|
||||
->sortBy('name')
|
||||
->filter(fn($item)=>Str::contains($item->name_lc,strtolower($request->term)));
|
||||
|
||||
return $attrs
|
||||
->map(fn($item)=>[
|
||||
'name'=>$item->name,
|
||||
'value'=>'',
|
||||
'category'=>__('Select attribute...')
|
||||
])
|
||||
->values();
|
||||
}
|
||||
}
|
||||
}
|
@@ -6,7 +6,6 @@ use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Crypt;
|
||||
use LdapRecord\Support\Arr;
|
||||
use LdapRecord\Models\Model;
|
||||
use LdapRecord\Query\Model\Builder;
|
||||
|
||||
use App\Classes\LDAP\Attribute;
|
||||
use App\Classes\LDAP\Attribute\Factory;
|
||||
|
@@ -17,7 +17,10 @@ class LoginObjectclassRule implements Rule
|
||||
public function passes(LdapRecord $user,?Eloquent $model=NULL): bool
|
||||
{
|
||||
if ($x=config('pla.login.objectclass')) {
|
||||
return count(array_intersect($user->objectclass,$x));
|
||||
return count(array_intersect(
|
||||
array_map('strtolower',$user?->objectclass ?: []),
|
||||
array_map('strtolower',$x)
|
||||
));
|
||||
|
||||
// Otherwise allow the user to login
|
||||
} else {
|
||||
|
@@ -16,8 +16,8 @@ return Application::configure(basePath: dirname(__DIR__))
|
||||
$middleware->appendToGroup(
|
||||
group: 'web',
|
||||
middleware: [
|
||||
AllowAnonymous::class,
|
||||
ApplicationSession::class,
|
||||
AllowAnonymous::class,
|
||||
SwapinAuthUser::class,
|
||||
ViewVariables::class,
|
||||
CheckUpdate::class,
|
||||
|
303
composer.lock
generated
303
composer.lock
generated
@@ -212,16 +212,16 @@
|
||||
},
|
||||
{
|
||||
"name": "directorytree/ldaprecord",
|
||||
"version": "v3.8.1",
|
||||
"version": "v3.8.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/DirectoryTree/LdapRecord.git",
|
||||
"reference": "9eb34c1b3588a853406373720a772ae4f3ed23d3"
|
||||
"reference": "cff35dc485cdfbc68e53948e4842e37e68770dde"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/DirectoryTree/LdapRecord/zipball/9eb34c1b3588a853406373720a772ae4f3ed23d3",
|
||||
"reference": "9eb34c1b3588a853406373720a772ae4f3ed23d3",
|
||||
"url": "https://api.github.com/repos/DirectoryTree/LdapRecord/zipball/cff35dc485cdfbc68e53948e4842e37e68770dde",
|
||||
"reference": "cff35dc485cdfbc68e53948e4842e37e68770dde",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -284,7 +284,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2025-03-06T00:35:47+00:00"
|
||||
"time": "2025-05-20T20:49:13+00:00"
|
||||
},
|
||||
{
|
||||
"name": "directorytree/ldaprecord-laravel",
|
||||
@@ -1199,16 +1199,16 @@
|
||||
},
|
||||
{
|
||||
"name": "laravel/framework",
|
||||
"version": "v11.44.7",
|
||||
"version": "v11.45.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laravel/framework.git",
|
||||
"reference": "00bc6ac91a6d577bf051c18ddaa638c0d221e1c7"
|
||||
"reference": "d0730deb427632004d24801be7ca1ed2c10fbc4e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laravel/framework/zipball/00bc6ac91a6d577bf051c18ddaa638c0d221e1c7",
|
||||
"reference": "00bc6ac91a6d577bf051c18ddaa638c0d221e1c7",
|
||||
"url": "https://api.github.com/repos/laravel/framework/zipball/d0730deb427632004d24801be7ca1ed2c10fbc4e",
|
||||
"reference": "d0730deb427632004d24801be7ca1ed2c10fbc4e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1229,7 +1229,7 @@
|
||||
"guzzlehttp/uri-template": "^1.0",
|
||||
"laravel/prompts": "^0.1.18|^0.2.0|^0.3.0",
|
||||
"laravel/serializable-closure": "^1.3|^2.0",
|
||||
"league/commonmark": "^2.6",
|
||||
"league/commonmark": "^2.7",
|
||||
"league/flysystem": "^3.25.1",
|
||||
"league/flysystem-local": "^3.25.1",
|
||||
"league/uri": "^7.5.1",
|
||||
@@ -1316,7 +1316,7 @@
|
||||
"league/flysystem-read-only": "^3.25.1",
|
||||
"league/flysystem-sftp-v3": "^3.25.1",
|
||||
"mockery/mockery": "^1.6.10",
|
||||
"orchestra/testbench-core": "^9.11.2",
|
||||
"orchestra/testbench-core": "^9.13.2",
|
||||
"pda/pheanstalk": "^5.0.6",
|
||||
"php-http/discovery": "^1.15",
|
||||
"phpstan/phpstan": "^2.0",
|
||||
@@ -1410,7 +1410,7 @@
|
||||
"issues": "https://github.com/laravel/framework/issues",
|
||||
"source": "https://github.com/laravel/framework"
|
||||
},
|
||||
"time": "2025-04-25T12:40:47+00:00"
|
||||
"time": "2025-05-20T15:15:58+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laravel/prompts",
|
||||
@@ -1661,16 +1661,16 @@
|
||||
},
|
||||
{
|
||||
"name": "league/commonmark",
|
||||
"version": "2.6.2",
|
||||
"version": "2.7.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/thephpleague/commonmark.git",
|
||||
"reference": "06c3b0bf2540338094575612f4a1778d0d2d5e94"
|
||||
"reference": "6fbb36d44824ed4091adbcf4c7d4a3923cdb3405"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/thephpleague/commonmark/zipball/06c3b0bf2540338094575612f4a1778d0d2d5e94",
|
||||
"reference": "06c3b0bf2540338094575612f4a1778d0d2d5e94",
|
||||
"url": "https://api.github.com/repos/thephpleague/commonmark/zipball/6fbb36d44824ed4091adbcf4c7d4a3923cdb3405",
|
||||
"reference": "6fbb36d44824ed4091adbcf4c7d4a3923cdb3405",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1707,7 +1707,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "2.7-dev"
|
||||
"dev-main": "2.8-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
@@ -1764,7 +1764,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2025-04-18T21:09:27+00:00"
|
||||
"time": "2025-05-05T12:20:28+00:00"
|
||||
},
|
||||
{
|
||||
"name": "league/config",
|
||||
@@ -2315,16 +2315,16 @@
|
||||
},
|
||||
{
|
||||
"name": "nesbot/carbon",
|
||||
"version": "3.9.0",
|
||||
"version": "3.9.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/CarbonPHP/carbon.git",
|
||||
"reference": "6d16a8a015166fe54e22c042e0805c5363aef50d"
|
||||
"reference": "ced71f79398ece168e24f7f7710462f462310d4d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/6d16a8a015166fe54e22c042e0805c5363aef50d",
|
||||
"reference": "6d16a8a015166fe54e22c042e0805c5363aef50d",
|
||||
"url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/ced71f79398ece168e24f7f7710462f462310d4d",
|
||||
"reference": "ced71f79398ece168e24f7f7710462f462310d4d",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -2417,7 +2417,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2025-03-27T12:57:33+00:00"
|
||||
"time": "2025-05-01T19:51:51+00:00"
|
||||
},
|
||||
{
|
||||
"name": "nette/schema",
|
||||
@@ -2569,31 +2569,31 @@
|
||||
},
|
||||
{
|
||||
"name": "nunomaduro/termwind",
|
||||
"version": "v2.3.0",
|
||||
"version": "v2.3.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/nunomaduro/termwind.git",
|
||||
"reference": "52915afe6a1044e8b9cee1bcff836fb63acf9cda"
|
||||
"reference": "dfa08f390e509967a15c22493dc0bac5733d9123"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/nunomaduro/termwind/zipball/52915afe6a1044e8b9cee1bcff836fb63acf9cda",
|
||||
"reference": "52915afe6a1044e8b9cee1bcff836fb63acf9cda",
|
||||
"url": "https://api.github.com/repos/nunomaduro/termwind/zipball/dfa08f390e509967a15c22493dc0bac5733d9123",
|
||||
"reference": "dfa08f390e509967a15c22493dc0bac5733d9123",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-mbstring": "*",
|
||||
"php": "^8.2",
|
||||
"symfony/console": "^7.1.8"
|
||||
"symfony/console": "^7.2.6"
|
||||
},
|
||||
"require-dev": {
|
||||
"illuminate/console": "^11.33.2",
|
||||
"laravel/pint": "^1.18.2",
|
||||
"illuminate/console": "^11.44.7",
|
||||
"laravel/pint": "^1.22.0",
|
||||
"mockery/mockery": "^1.6.12",
|
||||
"pestphp/pest": "^2.36.0",
|
||||
"phpstan/phpstan": "^1.12.11",
|
||||
"phpstan/phpstan-strict-rules": "^1.6.1",
|
||||
"symfony/var-dumper": "^7.1.8",
|
||||
"pestphp/pest": "^2.36.0 || ^3.8.2",
|
||||
"phpstan/phpstan": "^1.12.25",
|
||||
"phpstan/phpstan-strict-rules": "^1.6.2",
|
||||
"symfony/var-dumper": "^7.2.6",
|
||||
"thecodingmachine/phpstan-strict-rules": "^1.0.0"
|
||||
},
|
||||
"type": "library",
|
||||
@@ -2636,7 +2636,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/nunomaduro/termwind/issues",
|
||||
"source": "https://github.com/nunomaduro/termwind/tree/v2.3.0"
|
||||
"source": "https://github.com/nunomaduro/termwind/tree/v2.3.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -2652,7 +2652,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2024-11-21T10:39:51+00:00"
|
||||
"time": "2025-05-08T08:14:37+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpoption/phpoption",
|
||||
@@ -3429,16 +3429,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/console",
|
||||
"version": "v7.2.5",
|
||||
"version": "v7.2.6",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/console.git",
|
||||
"reference": "e51498ea18570c062e7df29d05a7003585b19b88"
|
||||
"reference": "0e2e3f38c192e93e622e41ec37f4ca70cfedf218"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/console/zipball/e51498ea18570c062e7df29d05a7003585b19b88",
|
||||
"reference": "e51498ea18570c062e7df29d05a7003585b19b88",
|
||||
"url": "https://api.github.com/repos/symfony/console/zipball/0e2e3f38c192e93e622e41ec37f4ca70cfedf218",
|
||||
"reference": "0e2e3f38c192e93e622e41ec37f4ca70cfedf218",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -3502,7 +3502,7 @@
|
||||
"terminal"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/console/tree/v7.2.5"
|
||||
"source": "https://github.com/symfony/console/tree/v7.2.6"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -3518,7 +3518,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2025-03-12T08:11:12+00:00"
|
||||
"time": "2025-04-07T19:09:28+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/css-selector",
|
||||
@@ -3949,16 +3949,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/http-foundation",
|
||||
"version": "v7.2.5",
|
||||
"version": "v7.2.6",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/http-foundation.git",
|
||||
"reference": "371272aeb6286f8135e028ca535f8e4d6f114126"
|
||||
"reference": "6023ec7607254c87c5e69fb3558255aca440d72b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/371272aeb6286f8135e028ca535f8e4d6f114126",
|
||||
"reference": "371272aeb6286f8135e028ca535f8e4d6f114126",
|
||||
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/6023ec7607254c87c5e69fb3558255aca440d72b",
|
||||
"reference": "6023ec7607254c87c5e69fb3558255aca440d72b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -4007,7 +4007,7 @@
|
||||
"description": "Defines an object-oriented layer for the HTTP specification",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/http-foundation/tree/v7.2.5"
|
||||
"source": "https://github.com/symfony/http-foundation/tree/v7.2.6"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -4023,20 +4023,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2025-03-25T15:54:33+00:00"
|
||||
"time": "2025-04-09T08:14:01+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/http-kernel",
|
||||
"version": "v7.2.5",
|
||||
"version": "v7.2.6",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/http-kernel.git",
|
||||
"reference": "b1fe91bc1fa454a806d3f98db4ba826eb9941a54"
|
||||
"reference": "f9dec01e6094a063e738f8945ef69c0cfcf792ec"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/http-kernel/zipball/b1fe91bc1fa454a806d3f98db4ba826eb9941a54",
|
||||
"reference": "b1fe91bc1fa454a806d3f98db4ba826eb9941a54",
|
||||
"url": "https://api.github.com/repos/symfony/http-kernel/zipball/f9dec01e6094a063e738f8945ef69c0cfcf792ec",
|
||||
"reference": "f9dec01e6094a063e738f8945ef69c0cfcf792ec",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -4121,7 +4121,7 @@
|
||||
"description": "Provides a structured process for converting a Request into a Response",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/http-kernel/tree/v7.2.5"
|
||||
"source": "https://github.com/symfony/http-kernel/tree/v7.2.6"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -4137,20 +4137,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2025-03-28T13:32:50+00:00"
|
||||
"time": "2025-05-02T09:04:03+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/mailer",
|
||||
"version": "v7.2.3",
|
||||
"version": "v7.2.6",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/mailer.git",
|
||||
"reference": "f3871b182c44997cf039f3b462af4a48fb85f9d3"
|
||||
"reference": "998692469d6e698c6eadc7ef37a6530a9eabb356"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/mailer/zipball/f3871b182c44997cf039f3b462af4a48fb85f9d3",
|
||||
"reference": "f3871b182c44997cf039f3b462af4a48fb85f9d3",
|
||||
"url": "https://api.github.com/repos/symfony/mailer/zipball/998692469d6e698c6eadc7ef37a6530a9eabb356",
|
||||
"reference": "998692469d6e698c6eadc7ef37a6530a9eabb356",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -4201,7 +4201,7 @@
|
||||
"description": "Helps sending emails",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/mailer/tree/v7.2.3"
|
||||
"source": "https://github.com/symfony/mailer/tree/v7.2.6"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -4217,20 +4217,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2025-01-27T11:08:17+00:00"
|
||||
"time": "2025-04-04T09:50:51+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/mime",
|
||||
"version": "v7.2.4",
|
||||
"version": "v7.2.6",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/mime.git",
|
||||
"reference": "87ca22046b78c3feaff04b337f33b38510fd686b"
|
||||
"reference": "706e65c72d402539a072d0d6ad105fff6c161ef1"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/mime/zipball/87ca22046b78c3feaff04b337f33b38510fd686b",
|
||||
"reference": "87ca22046b78c3feaff04b337f33b38510fd686b",
|
||||
"url": "https://api.github.com/repos/symfony/mime/zipball/706e65c72d402539a072d0d6ad105fff6c161ef1",
|
||||
"reference": "706e65c72d402539a072d0d6ad105fff6c161ef1",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -4285,7 +4285,7 @@
|
||||
"mime-type"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/mime/tree/v7.2.4"
|
||||
"source": "https://github.com/symfony/mime/tree/v7.2.6"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -4301,11 +4301,11 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2025-02-19T08:51:20+00:00"
|
||||
"time": "2025-04-27T13:34:41+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-ctype",
|
||||
"version": "v1.31.0",
|
||||
"version": "v1.32.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-ctype.git",
|
||||
@@ -4364,7 +4364,7 @@
|
||||
"portable"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.31.0"
|
||||
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.32.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -4384,7 +4384,7 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-intl-grapheme",
|
||||
"version": "v1.31.0",
|
||||
"version": "v1.32.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-intl-grapheme.git",
|
||||
@@ -4442,7 +4442,7 @@
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.31.0"
|
||||
"source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.32.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -4462,16 +4462,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-intl-idn",
|
||||
"version": "v1.31.0",
|
||||
"version": "v1.32.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-intl-idn.git",
|
||||
"reference": "c36586dcf89a12315939e00ec9b4474adcb1d773"
|
||||
"reference": "9614ac4d8061dc257ecc64cba1b140873dce8ad3"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/c36586dcf89a12315939e00ec9b4474adcb1d773",
|
||||
"reference": "c36586dcf89a12315939e00ec9b4474adcb1d773",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/9614ac4d8061dc257ecc64cba1b140873dce8ad3",
|
||||
"reference": "9614ac4d8061dc257ecc64cba1b140873dce8ad3",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -4525,7 +4525,7 @@
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.31.0"
|
||||
"source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.32.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -4541,11 +4541,11 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-09-09T11:45:10+00:00"
|
||||
"time": "2024-09-10T14:38:51+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-intl-normalizer",
|
||||
"version": "v1.31.0",
|
||||
"version": "v1.32.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-intl-normalizer.git",
|
||||
@@ -4606,7 +4606,7 @@
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.31.0"
|
||||
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.32.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -4626,19 +4626,20 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-mbstring",
|
||||
"version": "v1.31.0",
|
||||
"version": "v1.32.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-mbstring.git",
|
||||
"reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341"
|
||||
"reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/85181ba99b2345b0ef10ce42ecac37612d9fd341",
|
||||
"reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493",
|
||||
"reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-iconv": "*",
|
||||
"php": ">=7.2"
|
||||
},
|
||||
"provide": {
|
||||
@@ -4686,7 +4687,7 @@
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.31.0"
|
||||
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.32.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -4702,20 +4703,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-09-09T11:45:10+00:00"
|
||||
"time": "2024-12-23T08:48:59+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-php80",
|
||||
"version": "v1.31.0",
|
||||
"version": "v1.32.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-php80.git",
|
||||
"reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8"
|
||||
"reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/60328e362d4c2c802a54fcbf04f9d3fb892b4cf8",
|
||||
"reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/0cc9dd0f17f61d8131e7df6b84bd344899fe2608",
|
||||
"reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -4766,7 +4767,7 @@
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-php80/tree/v1.31.0"
|
||||
"source": "https://github.com/symfony/polyfill-php80/tree/v1.32.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -4782,11 +4783,11 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-09-09T11:45:10+00:00"
|
||||
"time": "2025-01-02T08:10:11+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-php83",
|
||||
"version": "v1.31.0",
|
||||
"version": "v1.32.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-php83.git",
|
||||
@@ -4842,7 +4843,7 @@
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-php83/tree/v1.31.0"
|
||||
"source": "https://github.com/symfony/polyfill-php83/tree/v1.32.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -4862,7 +4863,7 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-uuid",
|
||||
"version": "v1.31.0",
|
||||
"version": "v1.32.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-uuid.git",
|
||||
@@ -4921,7 +4922,7 @@
|
||||
"uuid"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-uuid/tree/v1.31.0"
|
||||
"source": "https://github.com/symfony/polyfill-uuid/tree/v1.32.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -5166,16 +5167,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/string",
|
||||
"version": "v7.2.0",
|
||||
"version": "v7.2.6",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/string.git",
|
||||
"reference": "446e0d146f991dde3e73f45f2c97a9faad773c82"
|
||||
"reference": "a214fe7d62bd4df2a76447c67c6b26e1d5e74931"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/string/zipball/446e0d146f991dde3e73f45f2c97a9faad773c82",
|
||||
"reference": "446e0d146f991dde3e73f45f2c97a9faad773c82",
|
||||
"url": "https://api.github.com/repos/symfony/string/zipball/a214fe7d62bd4df2a76447c67c6b26e1d5e74931",
|
||||
"reference": "a214fe7d62bd4df2a76447c67c6b26e1d5e74931",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -5233,7 +5234,7 @@
|
||||
"utf8"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/string/tree/v7.2.0"
|
||||
"source": "https://github.com/symfony/string/tree/v7.2.6"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -5249,20 +5250,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-11-13T13:31:26+00:00"
|
||||
"time": "2025-04-20T20:18:16+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/translation",
|
||||
"version": "v7.2.4",
|
||||
"version": "v7.2.6",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/translation.git",
|
||||
"reference": "283856e6981286cc0d800b53bd5703e8e363f05a"
|
||||
"reference": "e7fd8e2a4239b79a0fd9fb1fef3e0e7f969c6dc6"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/translation/zipball/283856e6981286cc0d800b53bd5703e8e363f05a",
|
||||
"reference": "283856e6981286cc0d800b53bd5703e8e363f05a",
|
||||
"url": "https://api.github.com/repos/symfony/translation/zipball/e7fd8e2a4239b79a0fd9fb1fef3e0e7f969c6dc6",
|
||||
"reference": "e7fd8e2a4239b79a0fd9fb1fef3e0e7f969c6dc6",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -5328,7 +5329,7 @@
|
||||
"description": "Provides tools to internationalize your application",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/translation/tree/v7.2.4"
|
||||
"source": "https://github.com/symfony/translation/tree/v7.2.6"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -5344,7 +5345,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2025-02-13T10:27:23+00:00"
|
||||
"time": "2025-04-07T19:09:28+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/translation-contracts",
|
||||
@@ -5500,16 +5501,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/var-dumper",
|
||||
"version": "v7.2.3",
|
||||
"version": "v7.2.6",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/var-dumper.git",
|
||||
"reference": "82b478c69745d8878eb60f9a049a4d584996f73a"
|
||||
"reference": "9c46038cd4ed68952166cf7001b54eb539184ccb"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/82b478c69745d8878eb60f9a049a4d584996f73a",
|
||||
"reference": "82b478c69745d8878eb60f9a049a4d584996f73a",
|
||||
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/9c46038cd4ed68952166cf7001b54eb539184ccb",
|
||||
"reference": "9c46038cd4ed68952166cf7001b54eb539184ccb",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -5563,7 +5564,7 @@
|
||||
"dump"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/var-dumper/tree/v7.2.3"
|
||||
"source": "https://github.com/symfony/var-dumper/tree/v7.2.6"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -5579,7 +5580,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2025-01-17T11:39:41+00:00"
|
||||
"time": "2025-04-09T08:14:01+00:00"
|
||||
},
|
||||
{
|
||||
"name": "tijsverkoyen/css-to-inline-styles",
|
||||
@@ -5638,16 +5639,16 @@
|
||||
},
|
||||
{
|
||||
"name": "vlucas/phpdotenv",
|
||||
"version": "v5.6.1",
|
||||
"version": "v5.6.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/vlucas/phpdotenv.git",
|
||||
"reference": "a59a13791077fe3d44f90e7133eb68e7d22eaff2"
|
||||
"reference": "24ac4c74f91ee2c193fa1aaa5c249cb0822809af"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/a59a13791077fe3d44f90e7133eb68e7d22eaff2",
|
||||
"reference": "a59a13791077fe3d44f90e7133eb68e7d22eaff2",
|
||||
"url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/24ac4c74f91ee2c193fa1aaa5c249cb0822809af",
|
||||
"reference": "24ac4c74f91ee2c193fa1aaa5c249cb0822809af",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -5706,7 +5707,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/vlucas/phpdotenv/issues",
|
||||
"source": "https://github.com/vlucas/phpdotenv/tree/v5.6.1"
|
||||
"source": "https://github.com/vlucas/phpdotenv/tree/v5.6.2"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -5718,7 +5719,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-07-20T21:52:34+00:00"
|
||||
"time": "2025-04-30T23:37:27+00:00"
|
||||
},
|
||||
{
|
||||
"name": "voku/portable-ascii",
|
||||
@@ -6075,16 +6076,16 @@
|
||||
},
|
||||
{
|
||||
"name": "hamcrest/hamcrest-php",
|
||||
"version": "v2.1.0",
|
||||
"version": "v2.1.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/hamcrest/hamcrest-php.git",
|
||||
"reference": "99ec86beb7da3604d57cd3ca3699d2853f53018d"
|
||||
"reference": "f8b1c0173b22fa6ec77a81fe63e5b01eba7e6487"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/hamcrest/hamcrest-php/zipball/99ec86beb7da3604d57cd3ca3699d2853f53018d",
|
||||
"reference": "99ec86beb7da3604d57cd3ca3699d2853f53018d",
|
||||
"url": "https://api.github.com/repos/hamcrest/hamcrest-php/zipball/f8b1c0173b22fa6ec77a81fe63e5b01eba7e6487",
|
||||
"reference": "f8b1c0173b22fa6ec77a81fe63e5b01eba7e6487",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -6120,9 +6121,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/hamcrest/hamcrest-php/issues",
|
||||
"source": "https://github.com/hamcrest/hamcrest-php/tree/v2.1.0"
|
||||
"source": "https://github.com/hamcrest/hamcrest-php/tree/v2.1.1"
|
||||
},
|
||||
"time": "2025-04-29T18:09:42+00:00"
|
||||
"time": "2025-04-30T06:54:44+00:00"
|
||||
},
|
||||
{
|
||||
"name": "mockery/mockery",
|
||||
@@ -6937,16 +6938,16 @@
|
||||
},
|
||||
{
|
||||
"name": "phpunit/phpunit",
|
||||
"version": "11.5.18",
|
||||
"version": "11.5.21",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/phpunit.git",
|
||||
"reference": "fc3e887c7f3f9917e1bf61e523413d753db00a17"
|
||||
"reference": "d565e2cdc21a7db9dc6c399c1fc2083b8010f289"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/fc3e887c7f3f9917e1bf61e523413d753db00a17",
|
||||
"reference": "fc3e887c7f3f9917e1bf61e523413d753db00a17",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/d565e2cdc21a7db9dc6c399c1fc2083b8010f289",
|
||||
"reference": "d565e2cdc21a7db9dc6c399c1fc2083b8010f289",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -6956,7 +6957,7 @@
|
||||
"ext-mbstring": "*",
|
||||
"ext-xml": "*",
|
||||
"ext-xmlwriter": "*",
|
||||
"myclabs/deep-copy": "^1.13.0",
|
||||
"myclabs/deep-copy": "^1.13.1",
|
||||
"phar-io/manifest": "^2.0.4",
|
||||
"phar-io/version": "^3.2.1",
|
||||
"php": ">=8.2",
|
||||
@@ -6969,7 +6970,7 @@
|
||||
"sebastian/code-unit": "^3.0.3",
|
||||
"sebastian/comparator": "^6.3.1",
|
||||
"sebastian/diff": "^6.0.2",
|
||||
"sebastian/environment": "^7.2.0",
|
||||
"sebastian/environment": "^7.2.1",
|
||||
"sebastian/exporter": "^6.3.0",
|
||||
"sebastian/global-state": "^7.0.2",
|
||||
"sebastian/object-enumerator": "^6.0.1",
|
||||
@@ -7018,7 +7019,7 @@
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
|
||||
"security": "https://github.com/sebastianbergmann/phpunit/security/policy",
|
||||
"source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.18"
|
||||
"source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.21"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -7042,7 +7043,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2025-04-22T06:09:49+00:00"
|
||||
"time": "2025-05-21T12:35:00+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/cli-parser",
|
||||
@@ -7421,23 +7422,23 @@
|
||||
},
|
||||
{
|
||||
"name": "sebastian/environment",
|
||||
"version": "7.2.0",
|
||||
"version": "7.2.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/environment.git",
|
||||
"reference": "855f3ae0ab316bbafe1ba4e16e9f3c078d24a0c5"
|
||||
"reference": "a5c75038693ad2e8d4b6c15ba2403532647830c4"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/855f3ae0ab316bbafe1ba4e16e9f3c078d24a0c5",
|
||||
"reference": "855f3ae0ab316bbafe1ba4e16e9f3c078d24a0c5",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/a5c75038693ad2e8d4b6c15ba2403532647830c4",
|
||||
"reference": "a5c75038693ad2e8d4b6c15ba2403532647830c4",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^11.0"
|
||||
"phpunit/phpunit": "^11.3"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-posix": "*"
|
||||
@@ -7473,15 +7474,27 @@
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/environment/issues",
|
||||
"security": "https://github.com/sebastianbergmann/environment/security/policy",
|
||||
"source": "https://github.com/sebastianbergmann/environment/tree/7.2.0"
|
||||
"source": "https://github.com/sebastianbergmann/environment/tree/7.2.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/sebastianbergmann",
|
||||
"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/sebastian/environment",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-07-03T04:54:44+00:00"
|
||||
"time": "2025-05-21T11:55:47+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/exporter",
|
||||
@@ -7972,16 +7985,16 @@
|
||||
},
|
||||
{
|
||||
"name": "spatie/backtrace",
|
||||
"version": "1.7.2",
|
||||
"version": "1.7.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/spatie/backtrace.git",
|
||||
"reference": "9807de6b8fecfaa5b3d10650985f0348b02862b2"
|
||||
"reference": "cd37a49fce7137359ac30ecc44ef3e16404cccbe"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/spatie/backtrace/zipball/9807de6b8fecfaa5b3d10650985f0348b02862b2",
|
||||
"reference": "9807de6b8fecfaa5b3d10650985f0348b02862b2",
|
||||
"url": "https://api.github.com/repos/spatie/backtrace/zipball/cd37a49fce7137359ac30ecc44ef3e16404cccbe",
|
||||
"reference": "cd37a49fce7137359ac30ecc44ef3e16404cccbe",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -8019,7 +8032,7 @@
|
||||
"spatie"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/spatie/backtrace/tree/1.7.2"
|
||||
"source": "https://github.com/spatie/backtrace/tree/1.7.4"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -8031,7 +8044,7 @@
|
||||
"type": "other"
|
||||
}
|
||||
],
|
||||
"time": "2025-04-28T14:55:53+00:00"
|
||||
"time": "2025-05-08T15:41:09+00:00"
|
||||
},
|
||||
{
|
||||
"name": "spatie/error-solutions",
|
||||
|
@@ -7,7 +7,6 @@ php=${PHP_DIR:-/app}
|
||||
composer=${COMPOSER_HOME:-/var/cache/composer}
|
||||
|
||||
SITE_USER=${SITE_USER:-www-data}
|
||||
MEMCACHED_START=${MEMCACHED_START:-FALSE}
|
||||
RUN_USER=$(id -u)
|
||||
[ "${RUN_USER}" = "0" ] && USE_SU=1
|
||||
|
||||
@@ -40,12 +39,6 @@ echo "* Started with [$@]"
|
||||
# Run any container setup
|
||||
[ -x /sbin/init-container ] && /sbin/init-container
|
||||
|
||||
# General Setup
|
||||
if [ -x /usr/bin/memcached -a "${MEMCACHED_START}" == "TRUE" ]; then
|
||||
echo "* Starting MEMCACHED..."
|
||||
/usr/bin/memcached -d -P /run/memcached/memcached.pid -u memcached
|
||||
fi
|
||||
|
||||
# Laravel Specific
|
||||
if [ -r artisan -a -e ${php}/.env ]; then
|
||||
echo "* Laravel Setup..."
|
||||
|
@@ -1 +1 @@
|
||||
v2.1.2-rel
|
||||
v2.1.4-rel
|
||||
|
@@ -33,8 +33,12 @@
|
||||
<div class="app-header-left">
|
||||
<div class="search-wrapper">
|
||||
<div class="input-holder">
|
||||
<input type="text" class="search-input" placeholder="Type to search">
|
||||
<button class="search-icon"><span></span></button>
|
||||
<input type="text" class="search-input" id="search" placeholder="Type to search">
|
||||
<button class="search-icon">
|
||||
<span></span>
|
||||
<div id="searching" class="d-none"><i class="fas fa-fw fa-spinner fa-pulse text-light"></i></div>
|
||||
</button>
|
||||
<div id="search_results" style="height: 300px; overflow: scroll"></div>
|
||||
</div>
|
||||
<button class="btn-close"></button>
|
||||
</div>
|
||||
@@ -160,6 +164,13 @@
|
||||
</div>
|
||||
|
||||
@section('page-scripts')
|
||||
<style>
|
||||
#search_results ul.typeahead.dropdown-menu {
|
||||
overflow: scroll;
|
||||
max-height: 300px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
$('button[id^="link-"]').on('click',function(item) {
|
||||
@@ -190,6 +201,70 @@
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
$('.search-wrapper input[id="search"]').typeahead({
|
||||
autoSelect: false,
|
||||
scrollHeight: 10,
|
||||
theme: 'bootstrap5',
|
||||
delay: 500,
|
||||
minLength: 2,
|
||||
items: {{ $search_limit ?? 100 }},
|
||||
selectOnBlur: false,
|
||||
appendTo: "#search_results",
|
||||
source: function(query,process) {
|
||||
search('{{ url('search') }}',query,process);
|
||||
},
|
||||
// Disable sorting and just return the items (items should be sorted by the ajax method)
|
||||
sorter: function(items) {
|
||||
return items;
|
||||
},
|
||||
matcher: function() { return true; },
|
||||
// Disable sorting and just return the items (items should by the ajax method)
|
||||
updater: function(item) {
|
||||
// If item has a data value, then we'll use that
|
||||
if (item.data && item.data.length)
|
||||
return item.data;
|
||||
|
||||
if (! item.value)
|
||||
return item.name+'=';
|
||||
|
||||
location.replace('/#'+item.value);
|
||||
location.reload();
|
||||
return '';
|
||||
},
|
||||
})
|
||||
.on('keyup keypress',function(event) {
|
||||
var key = event.keyCode || event.which;
|
||||
if (key === 13) {
|
||||
event.preventDefault();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
var search = _.debounce(function(url,query,process){
|
||||
$.ajax({
|
||||
url : url,
|
||||
type : 'POST',
|
||||
data : 'term=' + query,
|
||||
dataType : 'JSON',
|
||||
async : true,
|
||||
cache : false,
|
||||
beforeSend : function() {
|
||||
$('.search-wrapper div#searching').removeClass('d-none');
|
||||
$('.search-wrapper .search-icon span').addClass('d-none');
|
||||
},
|
||||
success : function(data) {
|
||||
// if json is null, means no match, won't do again.
|
||||
if(data==null || (data.length===0)) return;
|
||||
|
||||
process(data);
|
||||
},
|
||||
complete : function() {
|
||||
$('.search-wrapper div#searching').addClass('d-none');
|
||||
$('.search-wrapper .search-icon span').removeClass('d-none');
|
||||
}
|
||||
})
|
||||
}, 500);
|
||||
</script>
|
||||
@append
|
@@ -1,9 +1,7 @@
|
||||
@use(App\Ldap\Entry)
|
||||
|
||||
<!-- $o=Attribute::class -->
|
||||
<x-attribute.layout :edit="$edit=($edit ?? FALSE)" :new="$new=($new ?? FALSE)" :o="$o">
|
||||
<div class="col-12">
|
||||
@foreach(Arr::get(old($o->name_lc,[($langtag=($langtag ?? Entry::TAG_NOTAG))=>$new ? [NULL] : $o->tagValues($langtag)]),$langtag,[]) as $key => $value)
|
||||
@foreach(Arr::get(old($o->name_lc,[$langtag=>$new ? [NULL] : $o->tagValues($langtag)]),$langtag,[]) as $key => $value)
|
||||
@if($edit && (! $o->is_rdn))
|
||||
<div class="input-group has-validation">
|
||||
<input type="text" @class(['form-control','is-invalid'=>($e=$errors->get($o->name_lc.'.'.$langtag.'.'.$loop->index)),'mb-1','border-focus'=>! ($tv=$o->tagValuesOld($langtag))->contains($value),'bg-success-subtle'=>$updated]) name="{{ $o->name_lc }}[{{ $langtag }}][]" value="{{ $value }}" placeholder="{{ ! is_null($x=$tv->get($loop->index)) ? $x : '['.__('NEW').']' }}" @readonly(! $new) @disabled($o->isDynamic())>
|
||||
|
@@ -1,6 +1,6 @@
|
||||
<!-- @todo We are not handling redirect backs yet with updated photos -->
|
||||
<!-- $o=Binary\JpegPhoto::class -->
|
||||
<x-attribute.layout :edit="$edit" :new="$new" :o="$o" :langtag="$langtag">
|
||||
<x-attribute.layout :edit="$edit" :new="$new" :o="$o">
|
||||
<table class="table table-borderless p-0 m-0">
|
||||
@foreach($o->tagValuesOld() as $key => $value)
|
||||
<tr>
|
||||
|
@@ -1,10 +1,9 @@
|
||||
<!-- @todo We are not handling redirect backs yet with updated passwords -->
|
||||
<!-- $o=KrbPrincipleKey::class -->
|
||||
<x-attribute.layout :edit="$edit" :new="$new" :o="$o" :langtag="$langtag">
|
||||
@foreach($o->tagValuesOld($langtag) as $key => $value)
|
||||
<x-attribute.layout :edit="$edit" :new="$new" :o="$o">
|
||||
@foreach(($o->tagValues($langtag)->count() ? $o->tagValues($langtag) : [$langtag => NULL]) as $key => $value)
|
||||
@if($edit)
|
||||
<div class="input-group has-validation mb-3">
|
||||
<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="{{ md5($value) }}" @readonly(true)>
|
||||
<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">
|
||||
@if($e)
|
||||
|
@@ -1,6 +1,6 @@
|
||||
<!-- $o=KrbTicketFlags::class -->
|
||||
<x-attribute.layout :edit="$edit" :new="$new" :o="$o">
|
||||
@foreach(Arr::get(old($o->name_lc,[$langtag=>$o->tagValues($langtag)]),$langtag,[]) as $key => $value)
|
||||
@foreach(($o->tagValues($langtag)->count() ? $o->tagValues($langtag) : [$langtag => NULL]) as $key => $value)
|
||||
@if($edit)
|
||||
<div id="32"></div>
|
||||
<div id="16"></div>
|
||||
|
@@ -1,6 +1,6 @@
|
||||
<!-- $o=Attribute/ObjectClass::class -->
|
||||
<x-attribute.layout :edit="$edit" :new="$new" :o="$o" :langtag="$langtag">
|
||||
@foreach(Arr::get(old($o->name_lc,[$langtag=>$new ? [NULL] : $o->tagValues($langtag)]),$langtag,[]) as $key => $value)
|
||||
<x-attribute.layout :edit="$edit" :new="$new" :o="$o">
|
||||
@foreach(($o->tagValues($langtag)->count() ? $o->tagValues($langtag) : [$langtag => NULL]) as $key => $value)
|
||||
@if($edit)
|
||||
<x-attribute.widget.objectclass :o="$o" :edit="$edit" :new="$new" :langtag="$langtag" :updated="$updated" :value="$value" :loop="$loop" />
|
||||
@else
|
||||
|
@@ -1,11 +1,10 @@
|
||||
<!-- @todo We are not handling redirect backs yet with updated passwords -->
|
||||
<!-- $o=Password::class -->
|
||||
<x-attribute.layout :edit="$edit" :new="$new" :o="$o" :langtag="$langtag">
|
||||
@foreach($o->tagValuesOld($langtag) as $key => $value)
|
||||
<x-attribute.layout :edit="$edit" :new="$new" :o="$o">
|
||||
@foreach(($o->tagValues($langtag)->count() ? $o->tagValues($langtag) : [$langtag => NULL]) as $key => $value)
|
||||
@if($edit)
|
||||
<div class="input-group has-validation mb-3">
|
||||
<x-form.select id="userpassword_hash_{{$loop->index}}" name="userpassword_hash[{{ $langtag }}][]" :value="$o->hash($value)->id()" :options="$helpers" allowclear="false" :disabled="true"/>
|
||||
<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="{{ md5($value) }}" @readonly(true)>
|
||||
<x-form.select id="userpassword_hash_{{$loop->index}}" 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)>
|
||||
|
||||
<div class="invalid-feedback pb-2">
|
||||
@if($e)
|
||||
|
@@ -1,6 +1,6 @@
|
||||
<!-- $o=RDN::class -->
|
||||
<x-attribute.layout :edit="$edit" :new="$new" :o="$o">
|
||||
@foreach(($o->values->count() ? $o->values : ['']) as $value)
|
||||
@foreach(($o->values->count() ? $o->values : [NULL]) as $value)
|
||||
@if($edit)
|
||||
<div class="input-group has-validation mb-3">
|
||||
<select class="form-select @error('rdn')is-invalid @enderror" id="rdn" name="rdn">
|
||||
|
@@ -255,7 +255,9 @@
|
||||
@default
|
||||
@if($o->isDynamic()) @break @endif
|
||||
@php($clone=TRUE)
|
||||
<span @class(['btn','btn-sm','btn-outline-primary','mt-3','addable','d-none'=>(! $new)]) id="{{ $o->name }}-addnew"><i class="fas fa-fw fa-plus"></i> @lang('Add Value')</span>
|
||||
@if($o->values_old->count())
|
||||
<span @class(['btn','btn-sm','btn-outline-primary','mt-3','addable','d-none'=>(! $new)]) id="{{ $o->name }}-addnew"><i class="fas fa-fw fa-plus"></i> @lang('Add Value')</span>
|
||||
@endif
|
||||
|
||||
@section('page-scripts')
|
||||
@if($clone && $edit && $o->can_addvalues)
|
||||
|
5
resources/views/components/failed.blade.php
Normal file
5
resources/views/components/failed.blade.php
Normal file
@@ -0,0 +1,5 @@
|
||||
@if(session()->has('failed'))
|
||||
<div class="alert alert-danger p-2">
|
||||
<p class="m-0"><i class="fas fa-fw fa-thumbs-down"></i> {{ session()->pull('failed') }}</p>
|
||||
</div>
|
||||
@endif
|
@@ -1,7 +1,7 @@
|
||||
@use(App\Classes\LDAP\Attribute\Certificate)
|
||||
|
||||
<!-- $o=Certificate::class -->
|
||||
<x-attribute.layout :edit="$edit" :new="$new" :o="$o" langtag="binary">
|
||||
<x-attribute.layout :edit="$edit" :new="$new" :o="$o">
|
||||
@foreach($o->tagValuesOld('binary') as $key => $value)
|
||||
<!-- If this attribute is not handle, it'll be an Attribute::class, we'll just render it normally -->
|
||||
@if(($o instanceof Certificate) && $edit)
|
||||
|
@@ -1,5 +1,5 @@
|
||||
<!-- $o=CertificateList::class -->
|
||||
<x-attribute.layout :edit="$edit" :new="$new" :o="$o" langtag="binary">
|
||||
<x-attribute.layout :edit="$edit" :new="$new" :o="$o">
|
||||
@foreach($o->tagValuesOld('binary') as $key => $value)
|
||||
<!-- If this attribute is not handle, it'll be an Attribute::class, we'll just render it normally -->
|
||||
<span class="form-control mb-1"><pre class="m-0">{{ $o->render_item_old('binary.'.$key) }}</pre></span>
|
||||
|
@@ -13,7 +13,7 @@
|
||||
|
||||
<div class="row">
|
||||
<div class="col-12 pt-2">
|
||||
<x-form.select id="newattr" label="Select from..." :options="$o->getMissingAttributes()->sortBy('name')->unique('name')->map(fn($item)=>['id'=>$item->name,'value'=>$item->name_lc])"/>
|
||||
<x-form.select id="newattr" label="Select from..." :options="$o->getMissingAttributes()->sortBy('name')->unique('name')->map(fn($item)=>['id'=>$item->name,'value'=>$item->name])"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -11,6 +11,7 @@
|
||||
|
||||
@section('page_status')
|
||||
<x-error/>
|
||||
<x-failed/>
|
||||
@endsection
|
||||
|
||||
@section('main-content')
|
||||
|
@@ -67,6 +67,7 @@
|
||||
<x-note/>
|
||||
<x-error/>
|
||||
<x-updated/>
|
||||
<x-failed/>
|
||||
@endsection
|
||||
|
||||
@section('main-content')
|
||||
|
@@ -23,18 +23,51 @@
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-sm-8">
|
||||
<h3 class="mb-1">Welcome to phpLDAPadmin</h3>
|
||||
<h4 class="mb-3"><small>{{ config('app.version') }}</small></h4>
|
||||
<p>phpLDAPadmin (or PLA for short) is an LDAP data management tool for administrators.</p>
|
||||
<p>PLA aims to adhere to the LDAP standards so that it can interact with any LDAP server that implements those standards.</p>
|
||||
<h1 class="mb-2">Welcome to phpLDAPadmin</h1>
|
||||
<p>phpLDAPadmin (or PLA for short) is an LDAP (Lightweight Directory Access Protocol) data management tool for administrators.</p>
|
||||
<p>PLA provides an easy-to-use interface for browsing, searching, and modifying data in an LDAP directory. Essentially, it's a user-friendly alternative to using command-line tools for LDAP management.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<hr>
|
||||
<p>Version 2 is a complete re-write of PLA, leveraging the advancements and modernisation of web tools and methods, libraries since version 1 was released.</p>
|
||||
<p>You can support this application by letting us know which LDAP server you use (including version and platform).</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-12 col-sm-4">
|
||||
<span class="text-dark">
|
||||
<a class="link-opacity-50 link-opacity-100-hover link-dark" href="https://phpldapadmin.org"><i class="fas fa-fw fa-2x fa-globe me-1"></i></a>
|
||||
<a class="link-opacity-50 link-opacity-100-hover link-dark" href="https://github.com/leenooks/phpldapadmin"><i class="fab fa-fw fa-2x fa-github me-1"></i></a>
|
||||
<a class="link-opacity-50 link-opacity-100-hover link-dark" href="https://github.com/leenooks/phpLDAPadmin/discussions"><i class="fas fa-fw fa-2x fa-hand me-1"></i></a>
|
||||
<a class="link-opacity-50 link-opacity-100-hover link-dark" href="https://github.com/leenooks/phpLDAPadmin/issues"><i class="fas fa-fw fa-2x fa-bug me-1"></i></a>
|
||||
<a class="link-opacity-50 link-opacity-100-hover link-dark" href="https://hub.docker.com/r/phpldapadmin/phpldapadmin"><i class="fab fa-fw fa-2x fa-docker me-1"></i></a>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-sm-8 col-xl-4">
|
||||
<h5>Key Features and Functionality</h5>
|
||||
<ul class="list-unstyled">
|
||||
<li class="ps-0 p-1">
|
||||
<i class="fas fa-fw fa-globe me-2"></i> Easy To Use Web Interface
|
||||
</li>
|
||||
<li class="ps-0 p-1">
|
||||
<i class="fas fa-fw fa-sitemap me-2"></i> Hierarchical Tree View
|
||||
</li>
|
||||
<li class="ps-0 p-1">
|
||||
<i class="fas fa-fw fa-language me-2"></i> Multi-language Support
|
||||
</li>
|
||||
<li class="ps-0 p-1">
|
||||
<i class="fas fa-fw fa-file-export me-2"></i> LDIF Import/Export
|
||||
</li>
|
||||
<li class="ps-0 p-1">
|
||||
<i class="fas fa-fw fa-clipboard-list me-2"></i> Built using RFC Standards
|
||||
</li>
|
||||
<li class="ps-0 p-1">
|
||||
<i class="fas fa-fw fa-pen-to-square me-2"></i> Open Source
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -2,7 +2,7 @@
|
||||
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
use App\Http\Controllers\{AjaxController,HomeController};
|
||||
use App\Http\Controllers\{AjaxController,HomeController,SearchController};
|
||||
use App\Http\Controllers\Auth\LoginController;
|
||||
use App\Http\Middleware\AllowAnonymous;
|
||||
|
||||
@@ -27,6 +27,7 @@ Auth::routes([
|
||||
]);
|
||||
|
||||
Route::get('logout',[LoginController::class,'logout']);
|
||||
Route::post('search',[SearchController::class,'search']);
|
||||
|
||||
Route::controller(HomeController::class)->group(function() {
|
||||
Route::middleware(AllowAnonymous::class)->group(function() {
|
||||
|
242
tests/Feature/AttributeTagsTest.php
Normal file
242
tests/Feature/AttributeTagsTest.php
Normal file
@@ -0,0 +1,242 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature;
|
||||
|
||||
use App\Classes\LDAP\Attribute;
|
||||
use App\Ldap\Entry;
|
||||
use Tests\TestCase;
|
||||
|
||||
/**
|
||||
* This unit will test Attributes that are:
|
||||
* + no_attr_tag attributes vs those with attr_tags, AND
|
||||
* + md5 attributes vs those that are not md5 attributes
|
||||
*
|
||||
* objectClass (a no_attr_tags_attribute)
|
||||
* userPassword (a no_attr_tags_attribute, and an md5 attribute)
|
||||
* certificate (a no_attr_tags attribute)
|
||||
* [internal attribute] (which is a no_attr_tags attribute)
|
||||
* mail (a normal attribute)
|
||||
*
|
||||
* => no_lang_tag attributes
|
||||
* + ->values returns a Collection of values
|
||||
* + ->values_old return a Collection of old values
|
||||
* + ->tagValues() returns a Collection of values
|
||||
* + ->tagValuesOld() return a Collection of old values
|
||||
* + ->render_old_item() should be the raw value (unless an md5attribute, then the md5 value)
|
||||
* + ->render_new_item() should be the raw value (unless an md5attribute, then the md5 value)
|
||||
* + ->_values is array with only 1 key _null_ with an array of values
|
||||
* + ->_values_old is array with only 1 key _null_ with an array of values
|
||||
* + ->isDirty processing when there is a new value in the _null_ key and in another key (it should be ignored for no_attr_tags attributes)
|
||||
* + ->isDirty processing when there is a new value, and its an md5 attribute
|
||||
*
|
||||
* The goal here is that
|
||||
* + no_attr_tags attributes return an array of values not indexed by an attr_tag
|
||||
* + attr_tag attributes are an array of values indexed by an attr_tag
|
||||
* + md5 attributes will render the md5 value, and compare the md5 value when determining if it has changed
|
||||
*
|
||||
* This will mean that our views then can render attributes with tagValues() and render_xxx_item() without just by calling
|
||||
* those methods with the langtag for the attribute rendering
|
||||
*
|
||||
* Attributes that are no_attr_tag attributes should not render anything in non-default langtag views
|
||||
*/
|
||||
class AttributeTagsTest extends TestCase
|
||||
{
|
||||
private function read()
|
||||
{
|
||||
static $o = NULL;
|
||||
|
||||
if (is_null($o)) {
|
||||
$dn = 'cn=Bart Simpson,ou=People,o=Simpsons';
|
||||
$this->assertTrue($this->login());
|
||||
$this->assertEquals($dn,$o=config('server')->fetch($dn));
|
||||
}
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
||||
public function test_uid()
|
||||
{
|
||||
// Test UID, which can have attribute tags
|
||||
$o = $this->read();
|
||||
$new = ['newbart'];
|
||||
$o->uid = [
|
||||
'_null_' => $new,
|
||||
];
|
||||
|
||||
$oo = $o->getObject('uid');
|
||||
|
||||
$this->assertInstanceOf(Attribute::class,$oo);
|
||||
|
||||
// ->values returns a Collection of values
|
||||
// ->_values is array with only 1 key _null_ with an array of values
|
||||
$this->assertCount(1,$oo->values);
|
||||
$this->assertArrayHasKey(Entry::TAG_NOTAG,$oo->values);
|
||||
$this->assertCount(1,$oo->values[Entry::TAG_NOTAG]);
|
||||
|
||||
// ->values_old return a Collection of old values
|
||||
// ->_values_old is array with only 1 key _null_ with an array of values
|
||||
$this->assertCount(1,$oo->values_old);
|
||||
$this->assertArrayHasKey(Entry::TAG_NOTAG,$oo->values_old);
|
||||
$this->assertCount(1,$oo->values_old[Entry::TAG_NOTAG]);
|
||||
|
||||
// ->tagValues() returns a Collection of values
|
||||
$this->assertCount(1,$oo->tagValues());
|
||||
|
||||
// ->tagValuesOld() return a Collection of old values
|
||||
$this->assertCount(1,$oo->tagValuesOld());
|
||||
|
||||
// ->render_item_old() should be the raw value (unless an md5attribute, then the md5 value)
|
||||
$this->assertEquals('bart',$oo->render_item_old(Entry::TAG_NOTAG.'.0'));
|
||||
// ->render_item_new() should be the raw value (unless an md5attribute, then the md5 value)
|
||||
$this->assertEquals('newbart',$oo->render_item_new(Entry::TAG_NOTAG.'.0'));
|
||||
|
||||
// ->isDirty processing when there is a new value in the _null_ key and in another key (it should be ignored for no_attr_tags attributes)
|
||||
// ->isDirty processing when there is a new value, and its an md5 attribute
|
||||
$this->assertTrue($oo->isDirty());
|
||||
$this->assertCount(1,$x=$o->getDirty());
|
||||
$this->assertArrayHasKey('uid',$x);
|
||||
$this->assertCount(1,$x['uid']);
|
||||
$this->assertEquals($new,$x['uid']);
|
||||
}
|
||||
|
||||
public function test_objectclass()
|
||||
{
|
||||
// Test ObjectClass, which can NOT have attribute tags
|
||||
$o = $this->read();
|
||||
$newoc = [
|
||||
'inetOrgPerson',
|
||||
'posixAccount',
|
||||
'top',
|
||||
'shadowAccount',
|
||||
'inetLocalMailRecipient',
|
||||
];
|
||||
|
||||
$o->objectclass = [
|
||||
'_null_' => $newoc,
|
||||
];
|
||||
|
||||
$oo = $o->getObject('objectclass');
|
||||
|
||||
$this->assertInstanceOf(Attribute\ObjectClass::class,$oo);
|
||||
$this->assertTrue($oo->no_attr_tags);
|
||||
|
||||
// ->values returns a Collection of values
|
||||
// ->_values is array with only 1 key _null_ with an array of values
|
||||
$this->assertCount(5,$oo->values);
|
||||
$this->assertArrayNotHasKey(Entry::TAG_NOTAG,$oo->values);
|
||||
|
||||
// ->values_old return a Collection of old values
|
||||
// ->_values_old is array with only 1 key _null_ with an array of values
|
||||
$this->assertCount(4,$oo->values_old);
|
||||
$this->assertArrayNotHasKey(Entry::TAG_NOTAG,$oo->values_old);
|
||||
|
||||
// ->tagValues() returns a Collection of values
|
||||
$this->assertCount(5,$oo->tagValues());
|
||||
|
||||
// ->tagValuesOld() return a Collection of old values
|
||||
$this->assertCount(4,$oo->tagValuesOld());
|
||||
|
||||
// ->render_item_old() should be the raw value (unless an md5attribute, then the md5 value)
|
||||
$this->assertEquals('inetOrgPerson',$oo->render_item_old('0'));
|
||||
// ->render_item_new() should be the raw value (unless an md5attribute, then the md5 value)
|
||||
$this->assertEquals('inetLocalMailRecipient',$oo->render_item_new('4'));
|
||||
|
||||
// ->isDirty processing when there is a new value in the _null_ key and in another key (it should be ignored for no_attr_tags attributes)
|
||||
// ->isDirty processing when there is a new value, and its an md5 attribute
|
||||
$this->assertTrue($oo->isDirty());
|
||||
$this->assertCount(2,$x=$o->getDirty());
|
||||
$this->assertArrayHasKey('objectclass',$x);
|
||||
$this->assertCount(5,$x['objectclass']);
|
||||
$this->assertEquals($newoc,$x['objectclass']);
|
||||
}
|
||||
|
||||
public function test_userpassword()
|
||||
{
|
||||
// Test ObjectClass, which can NOT have attribute tags
|
||||
$o = $this->read();
|
||||
$new = [
|
||||
'test1234',
|
||||
];
|
||||
$o->userpassword = [
|
||||
'_null_' => $new,
|
||||
];
|
||||
|
||||
$oo = $o->getObject('userpassword');
|
||||
|
||||
$this->assertInstanceOf(Attribute\Password::class,$oo);
|
||||
$this->assertTrue($oo->no_attr_tags);
|
||||
|
||||
// ->values returns a Collection of values
|
||||
// ->_values is array with only 1 key _null_ with an array of values
|
||||
$this->assertCount(1,$oo->values);
|
||||
$this->assertArrayNotHasKey(Entry::TAG_NOTAG,$oo->values);
|
||||
|
||||
// ->values_old return a Collection of old values
|
||||
// ->_values_old is array with only 1 key _null_ with an array of values
|
||||
$this->assertCount(1,$oo->values_old);
|
||||
$this->assertArrayNotHasKey(Entry::TAG_NOTAG,$oo->values_old);
|
||||
|
||||
// ->tagValues() returns a Collection of values
|
||||
$this->assertCount(1,$oo->tagValues());
|
||||
|
||||
// ->tagValuesOld() return a Collection of old values
|
||||
$this->assertCount(1,$oo->tagValuesOld());
|
||||
|
||||
// ->render_item_old() should be the raw value (unless an md5attribute, then the md5 value)
|
||||
$this->assertEquals('{*clear*}****************',$oo->render_item_old('0'));
|
||||
// ->render_item_new() should be the raw value (unless an md5attribute, then the md5 value)
|
||||
$this->assertEquals('****************',$oo->render_item_new('0'));
|
||||
|
||||
// ->isDirty processing when there is a new value in the _null_ key and in another key (it should be ignored for no_attr_tags attributes)
|
||||
// ->isDirty processing when there is a new value, and its an md5 attribute
|
||||
$this->assertTrue($oo->isDirty());
|
||||
$this->assertCount(3,$x=$o->getDirty());
|
||||
$this->assertArrayHasKey('userpassword',$x);
|
||||
$this->assertCount(1,$x['userpassword']);
|
||||
$this->assertEquals($new,$x['userpassword']);
|
||||
}
|
||||
|
||||
public function test_userpassword_nochange()
|
||||
{
|
||||
// Test ObjectClass, which can NOT have attribute tags
|
||||
$o = $this->read();
|
||||
$new = [
|
||||
'd88d98df6727f87376c93e9676978146', // eatmyshorts
|
||||
];
|
||||
$o->userpassword = [
|
||||
'_null_' => $new,
|
||||
];
|
||||
|
||||
$oo = $o->getObject('userpassword');
|
||||
|
||||
$this->assertInstanceOf(Attribute\Password::class,$oo);
|
||||
$this->assertTrue($oo->no_attr_tags);
|
||||
|
||||
// ->values returns a Collection of values
|
||||
// ->_values is array with only 1 key _null_ with an array of values
|
||||
$this->assertCount(1,$oo->values);
|
||||
$this->assertArrayNotHasKey(Entry::TAG_NOTAG,$oo->values);
|
||||
|
||||
// ->values_old return a Collection of old values
|
||||
// ->_values_old is array with only 1 key _null_ with an array of values
|
||||
$this->assertCount(1,$oo->values_old);
|
||||
$this->assertArrayNotHasKey(Entry::TAG_NOTAG,$oo->values_old);
|
||||
|
||||
// ->tagValues() returns a Collection of values
|
||||
$this->assertCount(1,$oo->tagValues());
|
||||
|
||||
// ->tagValuesOld() return a Collection of old values
|
||||
$this->assertCount(1,$oo->tagValuesOld());
|
||||
|
||||
// ->render_item_old() should be the raw value (unless an md5attribute, then the md5 value)
|
||||
$this->assertEquals('{*clear*}****************',$oo->render_item_old('0'));
|
||||
// ->render_item_new() should be the raw value (unless an md5attribute, then the md5 value)
|
||||
$this->assertEquals('****************',$oo->render_item_new('0'));
|
||||
|
||||
// ->isDirty processing when there is a new value in the _null_ key and in another key (it should be ignored for no_attr_tags attributes)
|
||||
// ->isDirty processing when there is a new value, and its an md5 attribute
|
||||
$this->assertFalse($oo->isDirty());
|
||||
$this->assertCount(2,$x=$o->getDirty());
|
||||
$this->assertArrayNotHasKey('userpassword',$x);
|
||||
}
|
||||
}
|
@@ -20,6 +20,6 @@ class GetBaseDNTest extends TestCase
|
||||
|
||||
$this->assertIsObject($o);
|
||||
$this->assertCount(6,$o->toArray());
|
||||
$this->assertEquals('dc=Test',$o->first()->getDn());
|
||||
$this->assertEquals('c=AU',$o->first()->getDn());
|
||||
}
|
||||
}
|
||||
}
|
48
tests/Feature/ImportTest.php
Normal file
48
tests/Feature/ImportTest.php
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature;
|
||||
|
||||
use Illuminate\Http\UploadedFile;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Crypt;
|
||||
use Tests\TestCase;
|
||||
|
||||
class ImportTest extends TestCase
|
||||
{
|
||||
public function testLDIF_Import()
|
||||
{
|
||||
$dn = 'cn=Bart Simpson,ou=People,o=Simpsons';
|
||||
$import_file = __DIR__.'/data/ldif-import.ldif';
|
||||
|
||||
$this->assertTrue($this->login());
|
||||
$this->assertTrue(Auth::check());
|
||||
$this->actingAs(Auth::user());
|
||||
$this->assertFalse(config('ldap.cache.enabled'));
|
||||
|
||||
// Check that it exists
|
||||
$this->assertEquals($dn,$x=config('server')->fetch($dn));
|
||||
$this->assertTrue($x->exists);
|
||||
|
||||
// Delete the entry
|
||||
$x->delete();
|
||||
$this->assertEquals(NULL,config('server')->fetch($dn));
|
||||
|
||||
$file = new UploadedFile($import_file,'ldif-import.ldif',null,null,true);
|
||||
|
||||
$response = $this
|
||||
->actingAs(Auth::user())
|
||||
->from('/import')
|
||||
->post('/import/process/ldif',[
|
||||
'_token' => csrf_token(),
|
||||
'key'=>Crypt::encryptString('*import|_NOP'),
|
||||
'file' => $file,
|
||||
]);
|
||||
|
||||
//$response->dump();
|
||||
$response->assertSuccessful();
|
||||
|
||||
// Check that it hsa been created
|
||||
$this->assertEquals($dn,$x=config('server')->fetch($dn));
|
||||
$this->assertTrue($x->exists);
|
||||
}
|
||||
}
|
@@ -2,8 +2,8 @@
|
||||
|
||||
namespace Tests\Feature;
|
||||
|
||||
use LdapRecord\Container;
|
||||
use LdapRecord\Testing\DirectoryFake;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
use Tests\TestCase;
|
||||
|
||||
class LoginTest extends TestCase
|
||||
@@ -18,12 +18,10 @@ class LoginTest extends TestCase
|
||||
|
||||
public function test_admin_dn_login()
|
||||
{
|
||||
$username = 'cn=Admin,dc=Test';
|
||||
$password = 'test';
|
||||
$this->assertTrue($this->login());
|
||||
$this->assertTrue(Auth::check());
|
||||
|
||||
//DirectoryFake::setup();
|
||||
|
||||
$connection = Container::getDefaultConnection();
|
||||
$this->assertTrue($connection->auth()->attempt($username,$password));
|
||||
$this->assertTrue(Session::has('username_encrypt'));
|
||||
$this->assertTrue(Session::has('password_encrypt'));
|
||||
}
|
||||
}
|
||||
}
|
83
tests/Feature/data/ldif-import.ldif
Normal file
83
tests/Feature/data/ldif-import.ldif
Normal file
@@ -0,0 +1,83 @@
|
||||
# LDIF Export for cn=Bart Simpson,ou=People,o=Simpsons
|
||||
# Server: LDAP Server (ldap://ldap:389)
|
||||
# Total Entries: 1
|
||||
#
|
||||
# Generated by PLA (http://localhost) on January 12, 2024 12:39 pm
|
||||
# Exported by Anonymous
|
||||
# Version: v2.0.0-dev-00000000
|
||||
|
||||
version: 1
|
||||
# Entry 1: cn=Bart Simpson,ou=People,o=Simpsons
|
||||
dn: cn=Bart Simpson,ou=People,o=Simpsons
|
||||
audio: test
|
||||
cn: Bart Simpson
|
||||
gidNumber: 1000
|
||||
givenName: Bart
|
||||
homeDirectory: /home/users/simpsons/bart
|
||||
jpegPhoto:: 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
|
||||
l: Springfield
|
||||
mail: bart.simpson@example.com
|
||||
o: The Simpsons
|
||||
objectClass: inetOrgPerson
|
||||
objectClass: posixAccount
|
||||
objectClass: top
|
||||
objectClass: shadowAccount
|
||||
sn: Simpson
|
||||
st: 742 Evergreen Terrace
|
||||
telephoneNumber: +1 939 555 3126
|
||||
uid: bart
|
||||
uidNumber: 1000
|
||||
userPassword: eatmyshorts
|
@@ -3,10 +3,20 @@
|
||||
namespace Tests;
|
||||
|
||||
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Config;
|
||||
|
||||
use App\Classes\LDAP\Server;
|
||||
|
||||
abstract class TestCase extends BaseTestCase
|
||||
{
|
||||
use CreatesApplication;
|
||||
use CreatesApplication;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
Config::set('server',new Server());
|
||||
}
|
||||
|
||||
/**
|
||||
* Hack to get testing working
|
||||
@@ -19,4 +29,15 @@ abstract class TestCase extends BaseTestCase
|
||||
app()->instance('config', $config);
|
||||
app()->instance('events', $events);
|
||||
}
|
||||
|
||||
protected function login(): bool
|
||||
{
|
||||
//$username = 'cn=AdminUser,dc=Test';
|
||||
$username = 'admin';
|
||||
$password = 'password';
|
||||
|
||||
$this->post('/login',['uid'=>$username,'password'=>$password]);
|
||||
|
||||
return Auth::check() && (Auth::user()->getDN() === 'cn=AdminUser,dc=Test');
|
||||
}
|
||||
}
|
||||
|
4
tests/server/openldap/schema/modify/99-argon.ldif
Normal file
4
tests/server/openldap/schema/modify/99-argon.ldif
Normal file
@@ -0,0 +1,4 @@
|
||||
dn: cn=z-module{0},cn=config
|
||||
changetype: modify
|
||||
add: olcModuleLoad
|
||||
olcModuleLoad: argon2
|
Reference in New Issue
Block a user