Compare commits

..

2 Commits

Author SHA1 Message Date
Deon George
88f3c8faa7 Update already documented 2010-11-16 18:05:15 +11:00
Deon George
8c46ecf6c9 Defined undocumented parameters 2010-11-16 18:05:14 +11:00
955 changed files with 95716 additions and 47935 deletions

View File

@ -1,10 +0,0 @@
.dockerignore
.editorconfig
.env.testing
.git*
docker/
package.json
package-lock.json
phpunit.xml
webpack.mix.js
yarn.lock

View File

@ -1,18 +0,0 @@
root = true
[*]
charset = utf-8
end_of_line = lf
indent_size = 4
indent_style = tab
insert_final_newline = false
trim_trailing_whitespace = true
[*.md]
trim_trailing_whitespace = false
[*.{yml,yaml}]
indent_size = 2
[docker-compose.yml]
indent_size = 4

View File

@ -1,51 +0,0 @@
APP_NAME=Laravel
APP_ENV=production
APP_KEY=
APP_DEBUG=true
APP_URL=http://localhost
LOG_CHANNEL=stack
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=root
DB_PASSWORD=
BROADCAST_DRIVER=log
CACHE_DRIVER=file
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
MAIL_FROM_ADDRESS=null
MAIL_FROM_NAME="${APP_NAME}"
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=
LDAP_BASE_DN=
LDAP_USERNAME=
LDAP_PASSWORD=

View File

@ -1,51 +0,0 @@
APP_NAME=Laravel
APP_ENV=dev
APP_KEY=base64:KvIecx8zoy6RjcbJM8s98ZKs9IDGUHFVqBRn3Awfmso=
APP_DEBUG=true
APP_URL=http://localhost
LOG_CHANNEL=stack
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
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_BASE_DN="dc=Test"
LDAP_USERNAME="cn=admin,dc=Test"
LDAP_PASSWORD="test"
LDAP_CACHE=false

5
.gitattributes vendored
View File

@ -1,5 +0,0 @@
* text=auto
*.css linguist-vendored
*.scss linguist-vendored
*.js linguist-vendored
CHANGELOG.md export-ignore

13
.github/FUNDING.yml vendored
View File

@ -1,13 +0,0 @@
# These are supported funding model platforms
github: [leenooks]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
custom: ['https://www.buymeacoffee.com/dege']

View File

@ -1,38 +0,0 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem. Also include any logs or backtrace information
**LDAP Server details (please complete the following information):**
- OS: [e.g. iOS]
- Server Name [e.g. OpenLDAP, Windows AD,...]
- Version [e.g. 22]
**Smartphone (please complete the following information):**
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Browser [e.g. stock browser, safari]
- Version [e.g. 22]
**Additional context**
Add any other context about the problem here.

22
.gitignore vendored
View File

@ -1,19 +1,3 @@
/node_modules
/public/hot
/public/storage
/storage/*.key
/vendor
.env
.env.backup
.phpunit.result.cache
Homestead.json
Homestead.yaml
npm-debug.log
yarn-error.log
public/css/app.css
public/js/app.js
public/js/vendor.js
public/js/manifest.js
public/fonts/vendor
public/images/vendor
public/mix-manifest.json
config/config.php
queries/custom_*
templates/*/custom_*

View File

@ -1,38 +0,0 @@
stages:
- test
- build
- build-manifest
variables:
DOCKER_HOST: tcp://docker:2375
VERSION: latest
VERSIONARCH: ${VERSION}-${ARCH}
# This folder is cached between builds
# http://docs.gitlab.com/ce/ci/yaml/README.html#cache
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
- public/css/app.css
- public/js/app.js
- public/js/manifest.js
- public/js/vendor.js
- public/*/vendor/
- node_modules/
- vendor/
image: docker:latest
services:
- docker:dind
before_script:
- docker info && docker version
- echo "$CI_JOB_TOKEN" | docker login -u "$CI_REGISTRY_USER" "$CI_REGISTRY" --password-stdin
- if [ -n "$GITHUB_TOKEN" ]; then cat $GITHUB_TOKEN |base64 -d > auth.json; fi
include:
- .gitlab-test.yml
- .gitlab-docker-x86_64.yml
- .gitlab-docker-armv7l.yml
- .gitlab-docker-arm64.yml
- .gitlab-docker-manifest.yml

View File

@ -1,18 +0,0 @@
arm64:build:
variables:
ARCH: arm64
stage: build
script:
- if [ -f init ]; then chmod 500 init; fi
- echo -n ${CI_COMMIT_SHORT_SHA} > VERSION
- rm -rf node_modules database/seeds database/schema database/factories/*
- docker build -f docker/Dockerfile -t ${CI_REGISTRY_IMAGE}:${VERSIONARCH} .
- docker push ${CI_REGISTRY_IMAGE}:${VERSIONARCH}
tags:
- docker
- arm64
only:
- master

View File

@ -1,18 +0,0 @@
armv7l:build:
variables:
ARCH: armv7l
stage: build
script:
- if [ -f init ]; then chmod 500 init; fi
- echo -n ${CI_COMMIT_SHORT_SHA} > VERSION
- rm -rf node_modules database/seeds database/schema database/factories/*
- docker build -f docker/Dockerfile -t ${CI_REGISTRY_IMAGE}:${VERSIONARCH} .
- docker push ${CI_REGISTRY_IMAGE}:${VERSIONARCH}
tags:
- docker
- armv7l
only:
- master

View File

@ -1,10 +0,0 @@
x86_64:build-manifest:
stage: build-manifest
script:
- docker manifest create ${CI_REGISTRY_IMAGE}:${VERSION} ${CI_REGISTRY_IMAGE}:${VERSION}-x86_64 ${CI_REGISTRY_IMAGE}:${VERSION}-armv7l ${CI_REGISTRY_IMAGE}:${VERSION}-arm64
- docker manifest push --purge ${CI_REGISTRY_IMAGE}:${VERSION}
tags:
- docker
- x86_64
only:
- master

View File

@ -1,18 +0,0 @@
x86_64:build:
variables:
ARCH: x86_64
stage: build
script:
- if [ -f init ]; then chmod 500 init; fi
- echo -n ${CI_COMMIT_SHORT_SHA} > VERSION
- rm -rf node_modules database/seeds database/schema database/factories/*
- docker build -f docker/Dockerfile -t ${CI_REGISTRY_IMAGE}:${VERSIONARCH} .
- docker push ${CI_REGISTRY_IMAGE}:${VERSIONARCH}
tags:
- docker
- x86_64
only:
- master

View File

@ -1,52 +0,0 @@
test:
image: ${CI_REGISTRY}/leenooks/php:8.3-fpm-ldap-test
stage: test
# NOTE: This service is dependant on project file configuration, which is not there if the cache was deleted
# resulting in the testing to fail on the first run.
services:
- name: osixia/openldap:latest
alias: test_ldap
command: ["--loglevel","debug"]
variables:
LDAP_SEED_INTERNAL_LDIF_PATH: "${CI_PROJECT_DIR}/tests/server/openldap/data"
LDAP_SEED_INTERNAL_SCHEMA_PATH: "${CI_PROJECT_DIR}/tests/server/openldap/schema"
LDAP_BASE_DN: "dc=Test"
LDAP_DOMAIN: "Test"
LDAP_ADMIN_PASSWORD: test
#CI_DEBUG_SERVICES: "true"
tags:
- php
only:
- master
before_script:
- mv .env.testing .env
# Install npm and dependancies
- apk add --no-cache npm
- npm i
- npm run prod
# Install Composer and project dependencies.
- mkdir -p ${COMPOSER_HOME}
- if [ -n "$GITHUB_TOKEN" ]; then cat $GITHUB_TOKEN |base64 -d > ${COMPOSER_HOME}/auth.json; fi
- composer install
# Generate an application key. Re-cache.
- php artisan key:generate
script:
# Sleep if we need to, in case we want to jump in and see what is going on during the test
- if [ -n "$DEBUG_PAUSE" ]; then echo "Pausing for $DEBUG_PAUSE seconds, so you can jump into the containers"; sleep $DEBUG_PAUSE; fi
# run laravel tests
- XDEBUG_MODE=coverage php vendor/bin/phpunit --coverage-text --colors=never
# run frontend tests
# if you have any task for testing frontend
# set it in your package.json script
# comment this out if you don't have a frontend test
# npm test

23
INSTALL Normal file
View File

@ -0,0 +1,23 @@
For install instructions in non-English languages, see the wiki:
http://phpldapadmin.sourceforge.net
* Requirements
phpLDAPadmin requires the following:
a. A web server (Apache, IIS, etc).
b. PHP 5.0.0 or newer (with LDAP support)
* To install
1. Unpack the archive (if you're reading this, you already did that).
2. Put the resulting 'phpldapadmin' directory somewhere in your webroot.
3. Copy 'config.php.example' to 'config.php' and edit to taste (this is in the config/ directory).
4. Then, point your browser to the phpldapadmin directory.
* For additional help
See the wiki:
http://phpldapadmin.sourceforge.net
Join our mailing list:
https://lists.sourceforge.net/lists/listinfo/phpldapadmin-devel

View File

@ -1,50 +0,0 @@
# phpLDAPadmin
phpLDAPadmin is a web based LDAP data management tool for system administrators. It is commonly known and referred by many as "PLA".
PLA is designed to be compliant with LDAP RFCs, enabling it to be used with any LDAP server.
If you come across an LDAP server, where PLA exhibits problems, please open an issue with full details of the problem so that we can have it fixed.
For up to date information on PLA, please head to the [wiki](https://github.com/leenooks/phpLDAPadmin/wiki).
> **NOTE**: GIT **master** is currently in active development, and as such functionality may be missing, broken or not working as expected.
>
> If you are after a working version of PLA, please use one of the tagged releases.
## Demo
If you havent seen PLA in action, you can head here to the [demo](https://demo.phpldapadmin.org) site.
## Running the docker image
PLA v2 is available via docker for preview. (PLA v2 is still under heavy development.)
The container is the same one used for the demo site - but you'll be able to point it to your local LDAP server and see how things work.
Take a look at the [Docker Container](https://github.com/leenooks/phpLDAPadmin/wiki/Docker-Container) page for more details.
> Please let me know if you have any troubles with the container image, eg: usage of the container itself, or usage when it is pointing to your LDAP server.
>
> Open an issue (details below) with enough information for me to be able to recreate the problem. An `LDIF` will be invaluable if it is not handling data correctly.
## Getting Help
The best place to get help with PLA (new and old) is on [Stack Overflow](https://stackoverflow.com/tags/phpldapadmin/info).
## Found a bug?
If you have found a bug, and can provide detailed instructions so that it can be reproduced, please open an [issue](https://github.com/leenooks/phpLDAPadmin/issues) and provide those details.
Before opening a ticket, please check to see if it hasnt already been reported, and if it has, please provide any additional information that will help it be fixed.
*TIP*: Issues opened with:
* details enabling the problem to be reproduced,
* including (if appropriate) an LDIF with the data that exhibits the problem,
* a patch (or a git pull request) to fix the problem
will be looked at first :)
## THANK YOU
Over the years, many, many, many people have supported PLA with either their time, their coding or with financial donations.
I have tried to send an email to acknowledge each contribution, and if you havent seen anything personally from me, I am sorry, but please know that I do appreciate all the help I get, in whatever form it is provided.
Again, Thank You.
## License
[LICENSE](LICENSE)

View File

@ -1 +1 @@
00000000
RELEASE-1.2.0.5

3
app/.gitignore vendored
View File

@ -1,3 +0,0 @@
q*
!public/
!.gitignore

View File

@ -1,12 +0,0 @@
<?php
namespace App\Classes\LDAP\Attribute;
use App\Classes\LDAP\Attribute;
/**
* Represents an attribute whose values are binary
*/
class Binary extends Attribute
{
}

View File

@ -1,33 +0,0 @@
<?php
namespace App\Classes\LDAP\Attribute\Binary;
use Illuminate\Contracts\View\View;
use App\Classes\LDAP\Attribute\Binary;
use App\Traits\MD5Updates;
/**
* Represents an JpegPhoto Attribute
*/
final class JpegPhoto extends Binary
{
use MD5Updates;
public function __construct(string $name,array $values)
{
parent::__construct($name,$values);
$this->internal = FALSE;
}
public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE): View
{
return view('components.attribute.binary.jpegphoto')
->with('o',$this)
->with('edit',$edit)
->with('old',$old)
->with('new',$new)
->with('f',new \finfo);
}
}

View File

@ -1,58 +0,0 @@
<?php
namespace App\Classes\LDAP\Attribute;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Log;
use App\Classes\LDAP\Attribute;
/**
* This factory is used to return LDAP attributes as an object
*
* If there is no specific Attribute defined, then the default Attribute::class is return
*/
class Factory
{
private const LOGKEY = 'LAf';
/**
* Map of attributes to appropriate class
*/
public const map = [
'createtimestamp' => Internal\Timestamp::class,
'creatorsname' => Internal\DN::class,
'contextcsn' => Internal\CSN::class,
'entrycsn' => Internal\CSN::class,
'entrydn' => Internal\DN::class,
'entryuuid' => Internal\UUID::class,
'gidnumber' => GidNumber::class,
'hassubordinates' => Internal\HasSubordinates::class,
'jpegphoto' => Binary\JpegPhoto::class,
'modifytimestamp' => Internal\Timestamp::class,
'modifiersname' => Internal\DN::class,
'objectclass' => ObjectClass::class,
'structuralobjectclass' => Internal\StructuralObjectClass::class,
'subschemasubentry' => Internal\SubschemaSubentry::class,
'supportedcontrol' => Schema\OID::class,
'supportedextension' => Schema\OID::class,
'supportedfeatures' => Schema\OID::class,
'supportedsaslmechanisms' => Schema\Mechanisms::class,
'userpassword' => Password::class,
];
/**
* Create the new Object for an attribute
*
* @param string $attribute
* @param array $values
* @return Attribute
*/
public static function create(string $attribute,array $values): Attribute
{
$class = Arr::get(self::map,strtolower($attribute),Attribute::class);
Log::debug(sprintf('%s:Creating LDAP Attribute [%s] as [%s]',static::LOGKEY,$attribute,$class));
return new $class($attribute,$values);
}
}

View File

@ -1,12 +0,0 @@
<?php
namespace App\Classes\LDAP\Attribute;
use App\Classes\LDAP\Attribute;
/**
* Represents an GidNumber Attribute
*/
final class GidNumber extends Attribute
{
}

View File

@ -1,22 +0,0 @@
<?php
namespace App\Classes\LDAP\Attribute;
use Illuminate\Contracts\View\View;
use App\Classes\LDAP\Attribute;
/**
* Represents an attribute whose values are internal
*/
abstract class Internal extends Attribute
{
protected bool $is_internal = TRUE;
public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE): View
{
// @note Internal attributes cannot be edited
return view('components.attribute.internal')
->with('o',$this);
}
}

View File

@ -1,12 +0,0 @@
<?php
namespace App\Classes\LDAP\Attribute\Internal;
use App\Classes\LDAP\Attribute\Internal;
/**
* Represents an CSN Attribute
*/
final class CSN extends Internal
{
}

View File

@ -1,12 +0,0 @@
<?php
namespace App\Classes\LDAP\Attribute\Internal;
use App\Classes\LDAP\Attribute\Internal;
/**
* Represents an DN Attribute
*/
final class DN extends Internal
{
}

View File

@ -1,12 +0,0 @@
<?php
namespace App\Classes\LDAP\Attribute\Internal;
use App\Classes\LDAP\Attribute\Internal;
/**
* Represents an HasSubordinates Attribute
*/
final class HasSubordinates extends Internal
{
}

View File

@ -1,12 +0,0 @@
<?php
namespace App\Classes\LDAP\Attribute\Internal;
use App\Classes\LDAP\Attribute\Internal;
/**
* Represents an StructuralObjectClass Attribute
*/
final class StructuralObjectClass extends Internal
{
}

View File

@ -1,12 +0,0 @@
<?php
namespace App\Classes\LDAP\Attribute\Internal;
use App\Classes\LDAP\Attribute\Internal;
/**
* Represents an SubschemaSubentry Attribute
*/
final class SubschemaSubentry extends Internal
{
}

View File

@ -1,20 +0,0 @@
<?php
namespace App\Classes\LDAP\Attribute\Internal;
use Illuminate\Contracts\View\View;
use App\Classes\LDAP\Attribute\Internal;
/**
* Represents an attribute whose values are timestamps
*/
final class Timestamp extends Internal
{
public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE): View
{
// @note Internal attributes cannot be edited
return view('components.attribute.internal.timestamp')
->with('o',$this);
}
}

View File

@ -1,12 +0,0 @@
<?php
namespace App\Classes\LDAP\Attribute\Internal;
use App\Classes\LDAP\Attribute\Internal;
/**
* Represents an UUID Attribute
*/
final class UUID extends Internal
{
}

View File

@ -1,50 +0,0 @@
<?php
namespace App\Classes\LDAP\Attribute;
use Illuminate\Contracts\View\View;
use Illuminate\Support\Collection;
use App\Classes\LDAP\{Attribute,Server};
/**
* Represents an ObjectClass Attribute
*/
final class ObjectClass extends Attribute
{
// Which of the values is the structural object class
protected Collection $structural;
public function __construct(string $name,array $values)
{
parent::__construct($name,$values);
$this->structural = collect();
// Determine which of the values is the structural objectclass
foreach ($values as $oc) {
if ((new Server)->schema('objectclasses',$oc)->isStructural())
$this->structural->push($oc);
}
}
/**
* Is a specific value the structural objectclass
*
* @param string $value
* @return bool
*/
public function isStructural(string $value): bool
{
return $this->structural->search($value) !== FALSE;
}
public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE): View
{
return view('components.attribute.objectclass')
->with('o',$this)
->with('edit',$edit)
->with('old',$old)
->with('new',$new);
}
}

View File

@ -1,25 +0,0 @@
<?php
namespace App\Classes\LDAP\Attribute;
use Illuminate\Contracts\View\View;
use App\Classes\LDAP\Attribute;
use App\Traits\MD5Updates;
/**
* Represents an attribute whose values are passwords
*/
final class Password extends Attribute
{
use MD5Updates;
public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE): View
{
return view('components.attribute.password')
->with('o',$this)
->with('edit',$edit)
->with('old',$old)
->with('new',$new);
}
}

View File

@ -1,58 +0,0 @@
<?php
namespace App\Classes\LDAP\Attribute;
use Illuminate\Contracts\View\View;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Cache;
use App\Classes\LDAP\Attribute;
/**
* Represents an attribute whose values are schema related
*/
abstract class Schema extends Attribute
{
protected bool $internal = TRUE;
protected static function _get(string $filename,string $string,string $key): ?string
{
$array = Cache::remember($filename,86400,function() use ($filename) {
try {
$f = fopen($filename,'r');
} catch (\Exception $e) {
return NULL;
}
$result = collect();
while (! feof($f)) {
$line = trim(fgets($f));
if (! $line OR preg_match('/^#/',$line))
continue;
$fields = explode(':',$line);
$result->put($x=Arr::get($fields,0),[
'title'=>Arr::get($fields,1,$x),
'ref'=>Arr::get($fields,2),
'desc'=>Arr::get($fields,3,__('No description available, can you help with one?')),
]);
}
fclose($f);
return $result;
});
return Arr::get(($array ? $array->get($string) : []),$key);
}
public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE): View
{
// @note Schema attributes cannot be edited
return view('components.attribute.internal')
->with('o',$this);
}
}

View File

@ -1,42 +0,0 @@
<?php
namespace App\Classes\LDAP\Attribute\Schema;
use Illuminate\Contracts\View\View;
use App\Classes\LDAP\Attribute\Schema;
/**
* Represents a Mechanisms Attribute
*/
final class Mechanisms extends Schema
{
/**
* Given an SASL Mechanism name, returns a verbose description of the Mechanism.
* This function parses ldap_supported_saslmechanisms.txt and looks up the specified
* Mechanism, and returns the verbose message defined in that file.
*
* <code>
* "SCRAM-SHA-1" => array:3 [
* "title" => "Salted Challenge Response Authentication Mechanism (SCRAM) SHA1"
* "ref" => "RFC 5802"
* "desc" => "This specification describes a family of authentication mechanisms called the Salted Challenge Response Authentication Mechanism (SCRAM) which addresses the req ▶"
* ]
* </code>
*
* @param string $string The SASL Mechanism (ie, "SCRAM-SHA-1") of interest.
* @param string $key The title|ref|desc to return
* @return string|NULL
*/
public static function get(string $string,string $key): ?string
{
return parent::_get(config_path('ldap_supported_saslmechanisms.txt'),$string,$key);
}
public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE): View
{
// @note Schema attributes cannot be edited
return view('components.attribute.schema.mechanisms')
->with('o',$this);
}
}

View File

@ -1,43 +0,0 @@
<?php
namespace App\Classes\LDAP\Attribute\Schema;
use Illuminate\Contracts\View\View;
use App\Classes\LDAP\Attribute\Schema;
/**
* Represents an OID Attribute
*/
final class OID extends Schema
{
/**
* Given an LDAP OID number, returns a verbose description of the OID.
* This function parses ldap_supported_oids.txt and looks up the specified
* OID, and returns the verbose message defined in that file.
*
* <code>
* "1.3.6.1.4.1.4203.1.5.1" => array:3 [
* [title] => All Operational Attribute
* [ref] => RFC 3673
* [desc] => An LDAP extension which clients may use to request the return of all operational attributes.
* ]
* </code>
*
* @param string $string The OID number (ie, "1.3.6.1.4.1.4203.1.5.1") of the OID of interest.
* @param string $key The title|ref|desc to return
* @return string|null
* @testedby TranslateOidTest::testRootDSE()
*/
public static function get(string $string,string $key): ?string
{
return parent::_get(config_path('ldap_supported_oids.txt'),$string,$key);
}
public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE): View
{
// @note Schema attributes cannot be edited
return view('components.attribute.schema.oid')
->with('o',$this);
}
}

View File

@ -1,53 +0,0 @@
<?php
namespace App\Classes\LDAP;
use Illuminate\Support\Facades\Auth;
use LdapRecord\Query\Collection;
/**
* Export Class
*
* This abstract classes provides all the common methods and variables for the
* export classes.
*/
abstract class Export
{
// Line Break
protected string $br = "\r\n";
// Item(s) being Exported
protected Collection $items;
// Type of export
protected const type = 'Unknown';
public function __construct(Collection $items)
{
$this->items = $items;
}
abstract public function __toString(): string;
protected function header()
{
$output = '';
$output .= sprintf('# %s %s',__(static::type.' for'),($x=$this->items->first())).$this->br;
$output .= sprintf('# %s: %s (%s)',
__('Server'),
$x->getConnection()->getConfiguration()->get('name'),
$x->getConnection()->getLdapConnection()->getHost()).$this->br;
//$output .= sprintf('# %s: %s',__('Search Scope'),$this->scope).$this->br;
//$output .= sprintf('# %s: %s',__('Search Filter'),$this->entry->dn).$this->br;
$output .= sprintf('# %s: %s',__('Total Entries'),$this->items->count()).$this->br;
$output .= '#'.$this->br;
$output .= sprintf('# %s %s (%s) on %s',__('Generated by'),config('app.name'),config('app.url'),date('F j, Y g:i a')).$this->br;
$output .= sprintf('# %s %s',__('Exported by'),Auth::user() ?: 'Anonymous').$this->br;
$output .= sprintf('# %s: %s',__('Version'),config('app.version')).$this->br;
$output .= $this->br;
return $output;
}
}

View File

@ -1,78 +0,0 @@
<?php
namespace App\Classes\LDAP\Export;
use Illuminate\Support\Str;
use App\Classes\LDAP\Export;
/**
* Export from LDAP using an LDIF format
*/
class LDIF extends Export
{
// The maximum length of the ldif line
private int $line_length = 76;
protected const type = 'LDIF Export';
public function __toString(): string
{
$result = parent::header();
$result .= 'version: 1';
$result .= $this->br;
$c = 1;
foreach ($this->items as $o) {
if ($c > 1)
$result .= $this->br;
$title = (string)$o;
if (strlen($title) > $this->line_length)
$title = Str::of($title)->limit($this->line_length-3-5,'...'.substr($title,-5));
$result .= sprintf('# %s %s: %s',__('Entry'),$c++,$title).$this->br;
// Display DN
$result .= $this->multiLineDisplay(
Str::isAscii($o)
? sprintf('dn: %s',$o)
: sprintf('dn:: %s',base64_encode($o))
,$this->br);
// Display Attributes
foreach ($o->getObjects() as $ao) {
foreach ($ao->values as $value) {
$result .= $this->multiLineDisplay(
Str::isAscii($value)
? sprintf('%s: %s',$ao->name,$value)
: sprintf('%s:: %s',$ao->name,base64_encode($value))
,$this->br);
}
}
}
return $result;
}
/**
* Helper method to wrap LDIF lines
*
* @param string $str The line to be wrapped if needed.
*/
private function multiLineDisplay(string $str,string $br): string
{
$length_string = strlen($str);
$length_max = $this->line_length;
$output = '';
while ($length_string > $length_max) {
$output .= substr($str,0,$length_max).$br;
$str = ' '.substr($str,$length_max);
$length_string = strlen($str);
}
$output .= $str.$br;
return $output;
}
}

View File

@ -1,79 +0,0 @@
<?php
namespace App\Classes\LDAP;
use Illuminate\Support\Collection;
use App\Exceptions\Import\GeneralException;
use App\Exceptions\Import\ObjectExistsException;
use App\Ldap\Entry;
/**
* Import Class
*
* This abstract classes provides all the common methods and variables for the
* import classes.
*/
abstract class Import
{
// Valid LDIF commands
protected const LDAP_IMPORT_ADD = 1;
protected const LDAP_IMPORT_DELETE = 2;
protected const LDAP_IMPORT_MODRDN = 3;
protected const LDAP_IMPORT_MODDN = 4;
protected const LDAP_IMPORT_MODIFY = 5;
protected const LDAP_ACTIONS = [
'add' => self::LDAP_IMPORT_ADD,
'delete' => self::LDAP_IMPORT_DELETE,
'modrdn' => self::LDAP_IMPORT_MODRDN,
'moddn' => self::LDAP_IMPORT_MODDN,
'modify' => self::LDAP_IMPORT_MODIFY,
];
// The import data to process
protected string $input;
// The attributes the server knows about
protected Collection $server_attributes;
public function __construct(string $input) {
$this->input = $input;
$this->server_attributes = config('server')->schema('attributetypes');
}
/**
* Attempt to commit an entry and return the result.
*
* @param Entry $o
* @param int $action
* @return Collection
* @throws GeneralException
* @throws ObjectExistsException
*/
final protected function commit(Entry $o,int $action): Collection
{
switch ($action) {
case static::LDAP_IMPORT_ADD:
try {
$o->save();
} catch (\Exception $e) {
return collect([
'dn'=>$o->getDN(),
'result'=>sprintf('%d: %s (%s)',
($x=$e->getDetailedError())->getErrorCode(),
$x->getErrorMessage(),
$x->getDiagnosticMessage(),
)
]);
}
return collect(['dn'=>$o->getDN(),'result'=>__('Created')]);
default:
throw new GeneralException('Unhandled action during commit: '.$action);
}
}
abstract public function process(): Collection;
}

View File

@ -1,233 +0,0 @@
<?php
namespace App\Classes\LDAP\Import;
use Illuminate\Support\Arr;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log;
use Nette\NotImplementedException;
use App\Classes\LDAP\Import;
use App\Exceptions\Import\{GeneralException,VersionException};
use App\Ldap\Entry;
/**
* Import LDIF to LDAP using an LDIF format
*
* The LDIF spec is described by RFC2849
* http://www.ietf.org/rfc/rfc2849.txt
*/
class LDIF extends Import
{
private const LOGKEY = 'ILF';
public function process(): Collection
{
$c = 0;
$action = NULL;
$attribute = NULL;
$base64encoded = FALSE;
$o = NULL;
$value = '';
$version = NULL;
$result = collect();
// @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));
$line = trim($line);
// If the line starts with a comment, ignore it
if (preg_match('/^#/',$line))
continue;
// If we have a blank line, then that completes this command
if (! $line) {
if (! is_null($o)) {
// Add the last attribute;
$o->addAttribute($attribute,$base64encoded ? base64_decode($value) : $value);
Log::debug(sprintf('%s: Committing Entry [%s]',self::LOGKEY,$o->getDN()));
// Commit
$result->push($this->commit($o,$action));
$result->last()->put('line',$c);
$o = NULL;
$action = NULL;
$base64encoded = FALSE;
$attribute = NULL;
$value = '';
// Else its a blank line
}
continue;
}
$m = [];
preg_match('/^([a-zA-Z0-9;-]+)(:+)\s+(.*)$/',$line,$m);
switch ($x=Arr::get($m,1)) {
case 'changetype':
if ($m[2] !== ':')
throw new GeneralException(sprintf('ChangeType cannot be base64 encoded set at [%d]. (line %d)',$version,$c));
switch ($m[3]) {
// if (preg_match('/^changetype:[ ]*(delete|add|modrdn|moddn|modify)/i',$lines[0])) {
default:
throw new NotImplementedException(sprintf('Unknown change type [%s]? (line %d)',$m[3],$c));
}
break;
case 'version':
if (! is_null($version))
throw new VersionException(sprintf('Version has already been set at [%d]. (line %d)',$version,$c));
if ($m[2] !== ':')
throw new VersionException(sprintf('Version cannot be base64 encoded set at [%d]. (line %d)',$version,$c));
$version = (int)$m[3];
break;
// Treat it as an attribute
default:
// 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));
// add to last attr value
continue 2;
}
// We are ready to create the entry or add the attribute
if ($attribute) {
if ($attribute === 'dn') {
if (! is_null($o))
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));
//$o = Entry::find($dn);
// If it doesnt exist, we'll create it
//if (! $o) {
$o = new Entry;
$o->setDn($dn);
//}
$action = self::LDAP_IMPORT_ADD;
} else {
Log::debug(sprintf('%s: Adding Attribute [%s] value [%s] (%d)',self::LOGKEY,$attribute,$value,$c));
if ($value)
$o->addAttribute($attribute,$base64encoded ? base64_decode($value) : $value);
else
throw new GeneralException(sprintf('Attribute has no value [%s] (line %d)',$attribute,$c));
}
}
// Start of a new attribute
$base64encoded = ($m[2] === '::');
// @todo Need to parse attributes with ';' options
$attribute = $m[1];
$value = $m[3];
Log::debug(sprintf('%s: New Attribute [%s] with [%s] (%d)',self::LOGKEY,$attribute,$value,$c));
}
if ($version !== 1)
throw new VersionException('LDIF import cannot handle version: '.($version ?: __('NOT DEFINED')));
}
// We may still have a pending action
if ($action) {
// Add the last attribute;
$o->addAttribute($attribute,$base64encoded ? base64_decode($value) : $value);
Log::debug(sprintf('%s: Committing Entry [%s]',self::LOGKEY,$o->getDN()));
// Commit
$result->push($this->commit($o,$action));
$result->last()->put('line',$c);
}
return $result;
}
public function readEntry() {
static $haveVersion = false;
if ($lines = $this->nextLines()) {
$server = $this->getServer();
# The first line should be the DN
if (preg_match('/^dn:/',$lines[0])) {
list($text,$dn) = $this->getAttrValue(array_shift($lines));
# The second line should be our changetype
if (preg_match('/^changetype:[ ]*(delete|add|modrdn|moddn|modify)/i',$lines[0])) {
$attrvalue = $this->getAttrValue($lines[0]);
$changetype = $attrvalue[1];
array_shift($lines);
} else
$changetype = 'add';
$this->template = new Template($this->server_id,null,null,$changetype);
switch ($changetype) {
case 'add':
$rdn = get_rdn($dn);
$container = $server->getContainer($dn);
$this->template->setContainer($container);
$this->template->accept();
$this->getAddDetails($lines);
$this->template->setRDNAttributes($rdn);
return $this->template;
break;
case 'modify':
if (! $server->dnExists($dn))
return $this->error(sprintf('%s %s',_('DN does not exist'),$dn),$lines);
$this->template->setDN($dn);
$this->template->accept(false,true);
return $this->getModifyDetails($lines);
break;
case 'moddn':
case 'modrdn':
if (! $server->dnExists($dn))
return $this->error(sprintf('%s %s',_('DN does not exist'),$dn),$lines);
$this->template->setDN($dn);
$this->template->accept();
return $this->getModRDNAttributes($lines);
break;
default:
if (! $server->dnExists($dn))
return $this->error(_('Unkown change type'),$lines);
}
} else
return $this->error(_('A valid dn line is required'),$lines);
} else
return false;
}
}

View File

@ -1,598 +0,0 @@
<?php
namespace App\Classes\LDAP\Schema;
use Illuminate\Support\Arr;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log;
/**
* Represents an LDAP AttributeType
*
* @package phpLDAPadmin
* @subpackage Schema
*/
final class AttributeType extends Base {
// The attribute from which this attribute inherits (if any)
private ?string $sup_attribute = NULL;
// Array of AttributeTypes which inherit from this one
private Collection $children;
// The equality rule used
private ?string $equality = NULL;
// The ordering of the attributeType
private ?string $ordering = NULL;
// Supports substring matching?
private ?string $sub_str_rule = NULL;
// The full syntax string, ie 1.2.3.4{16}
private ?string $syntax = NULL;
private ?string $syntax_oid = NULL;
// boolean: is single valued only?
private bool $is_single_value = FALSE;
// boolean: is collective?
private bool $is_collective = FALSE;
// boolean: can use modify?
private bool $is_no_user_modification = FALSE;
// The usage string set by the LDAP schema
private ?string $usage = NULL;
// An array of alias attribute names, strings
private Collection $aliases;
// The max number of characters this attribute can be
private ?int $max_length = NULL;
// A string description of the syntax type (taken from the LDAPSyntaxes)
/**
* @deprecated - reference syntaxes directly if possible
* @var string
*/
private ?string $type = NULL;
// An array of objectClasses which use this attributeType (must be set by caller)
private Collection $used_in_object_classes;
// A list of object class names that require this attribute type.
private Collection $required_by_object_classes;
// This attribute has been forced a MAY attribute by the configuration.
private bool $forced_as_may = FALSE;
/**
* Creates a new AttributeType object from a raw LDAP AttributeType string.
*
* eg: ( 2.5.4.0 NAME 'objectClass' DESC 'RFC4512: object classes of the entity' EQUALITY objectIdentifierMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )
*/
public function __construct(string $line) {
Log::debug(sprintf('Parsing AttributeType [%s]',$line));
parent::__construct($line);
$strings = preg_split('/[\s,]+/',$line,-1,PREG_SPLIT_DELIM_CAPTURE);
// Init
$this->children = collect();
$this->aliases = collect();
$this->used_in_object_classes = collect();
$this->required_by_object_classes = collect();
for ($i=0; $i < count($strings); $i++) {
switch ($strings[$i]) {
case '(':
case ')':
break;
case 'NAME':
// @note Some schema's return a (' instead of a ( '
if ($strings[$i+1] != '(' && ! preg_match('/^\(/',$strings[$i+1])) {
do {
$this->name .= (strlen($this->name) ? ' ' : '').$strings[++$i];
} while (! preg_match("/\'$/s",$strings[$i]));
// This attribute has no aliases
//$this->aliases = collect();
} else {
$i++;
do {
// In case we came here becaues of a ('
if (preg_match('/^\(/',$strings[$i]))
$strings[$i] = preg_replace('/^\(/','',$strings[$i]);
else
$i++;
$this->name .= (strlen($this->name) ? ' ' : '').$strings[++$i];
} while (! preg_match("/\'$/s",$strings[$i]));
// Add alias names for this attribute
while ($strings[++$i] != ')') {
$alias = $strings[$i];
$alias = preg_replace("/^\'(.*)\'$/",'$1',$alias);
$this->addAlias($alias);
}
}
$this->name = preg_replace("/^\'(.*)\'$/",'$1',$this->name);
Log::debug(sprintf('- Case NAME returned (%s)',$this->name),['aliases'=>$this->aliases]);
break;
case 'DESC':
do {
$this->description .= (strlen($this->description) ? ' ' : '').$strings[++$i];
} while (! preg_match("/\'$/s",$strings[$i]));
$this->description = preg_replace("/^\'(.*)\'$/",'$1',$this->description);
Log::debug(sprintf('- Case DESC returned (%s)',$this->description));
break;
case 'OBSOLETE':
$this->is_obsolete = TRUE;
Log::debug(sprintf('- Case OBSOLETE returned (%s)',$this->is_obsolete));
break;
case 'SUP':
$i++;
$this->sup_attribute = preg_replace("/^\'(.*)\'$/",'$1',$strings[$i]);
Log::debug(sprintf('- Case SUP returned (%s)',$this->sup_attribute));
break;
case 'EQUALITY':
$this->equality = $strings[++$i];
Log::debug(sprintf('- Case EQUALITY returned (%s)',$this->equality));
break;
case 'ORDERING':
$this->ordering = $strings[++$i];
Log::debug(sprintf('- Case ORDERING returned (%s)',$this->ordering));
break;
case 'SUBSTR':
$this->sub_str_rule = $strings[++$i];
Log::debug(sprintf('- Case SUBSTR returned (%s)',$this->sub_str_rule));
break;
case 'SYNTAX':
$this->syntax = $strings[++$i];
$this->syntax_oid = preg_replace('/{\d+}$/','',$this->syntax);
Log::debug(sprintf('/ Evaluating SYNTAX returned (%s) [%s]',$this->syntax,$this->syntax_oid));
// Does this SYNTAX string specify a max length (ie, 1.2.3.4{16})
$m = [];
if (preg_match('/{(\d+)}$/',$this->syntax,$m))
$this->max_length = $m[1];
else
$this->max_length = NULL;
if ($i < count($strings) - 1 && $strings[$i+1] == '{')
do {
$this->name .= ' '.$strings[++$i];
} while ($strings[$i] != '}');
$this->syntax = preg_replace("/^\'(.*)\'$/",'$1',$this->syntax);
$this->syntax_oid = preg_replace("/^\'(.*)\'$/",'$1',$this->syntax_oid);
Log::debug(sprintf('- Case SYNTAX returned (%s) [%s] {%d}',$this->syntax,$this->syntax_oid,$this->max_length));
break;
case 'SINGLE-VALUE':
$this->is_single_value = TRUE;
Log::debug(sprintf('- Case SINGLE-VALUE returned (%s)',$this->is_single_value));
break;
case 'COLLECTIVE':
$this->is_collective = TRUE;
Log::debug(sprintf('- Case COLLECTIVE returned (%s)',$this->is_collective));
break;
case 'NO-USER-MODIFICATION':
$this->is_no_user_modification = TRUE;
Log::debug(sprintf('- Case NO-USER-MODIFICATION returned (%s)',$this->is_no_user_modification));
break;
case 'USAGE':
$this->usage = $strings[++$i];
Log::debug(sprintf('- Case USAGE returned (%s)',$this->usage));
break;
// @note currently not captured
case 'X-ORDERED':
Log::error(sprintf('- Case X-ORDERED returned (%s)',$strings[++$i]));
break;
// @note currently not captured
case 'X-ORIGIN':
$value = '';
do {
$value .= (strlen($value) ? ' ' : '').$strings[++$i];
} while (! preg_match("/\'$/s",$strings[$i]));
Log::error(sprintf('- Case X-ORIGIN returned (%s)',$value));
break;
default:
if (preg_match('/[\d\.]+/i',$strings[$i]) && ($i === 1)) {
$this->oid = $strings[$i];
Log::debug(sprintf('- Case default returned (%s)',$this->oid));
} elseif ($strings[$i])
Log::alert(sprintf('! Case default discovered a value NOT parsed (%s)',$strings[$i]),['line'=>$line]);
}
}
}
public function __clone()
{
// When we clone, we need to break the reference too
$this->aliases = clone $this->aliases;
}
public function __get(string $key): mixed
{
switch ($key) {
case 'aliases': return $this->aliases;
case 'children': return $this->children;
case 'forced_as_may': return $this->forced_as_may;
case 'is_collective': return $this->is_collective;
case 'is_editable': return ! $this->is_no_user_modification;
case 'is_no_user_modification': return $this->is_no_user_modification;
case 'is_single_value': return $this->is_single_value;
case 'equality': return $this->equality;
case 'max_length': return $this->max_length;
case 'ordering': return $this->ordering;
case 'required_by_object_classes': return $this->required_by_object_classes;
case 'sub_str_rule': return $this->sub_str_rule;
case 'sup_attribute': return $this->sup_attribute;
case 'syntax': return $this->syntax;
case 'syntax_oid': return $this->syntax_oid;
case 'type': return $this->type;
case 'usage': return $this->usage;
case 'used_in_object_classes': return $this->used_in_object_classes;
case 'validation': return Arr::get(config('ldap.validation'),$this->name_lc);
default: return parent::__get($key);
}
}
/**
* Adds an attribute name to the alias array.
*
* @param string $alias The name of a new attribute to add to this attribute's list of aliases.
*/
public function addAlias(string $alias): void
{
$this->aliases->push($alias);
}
/**
* Children of this attribute type that inherit from this one
*
* @param string $child
* @return void
*/
public function addChild(string $child): void
{
$this->children->push($child);
}
/**
* Adds an objectClass name to this attribute's list of "required by" objectClasses,
* that is the list of objectClasses which must have this attribute.
*
* @param string $name The name of the objectClass to add.
*/
public function addRequiredByObjectClass(string $name): void
{
if ($this->required_by_object_classes->search($name) === FALSE)
$this->required_by_object_classes->push($name);
}
/**
* Adds an objectClass name to this attribute's list of "used in" objectClasses,
* that is the list of objectClasses which provide this attribute.
*
* @param string $name The name of the objectClass to add.
*/
public function addUsedInObjectClass(string $name): void
{
if ($this->used_in_object_classes->search($name) === FALSE)
$this->used_in_object_classes->push($name);
}
/**
* Gets the names of attributes that are an alias for this attribute (if any).
*
* @return Collection An array of names of attributes which alias this attribute or
* an empty array if no attribute aliases this object.
* @deprecated use class->aliases
*/
public function getAliases(): Collection
{
return $this->aliases;
}
/**
* Gets this attribute's equality string
*
* @return string
* @deprecated use $this->equality
*/
public function getEquality()
{
return $this->equality;
}
/**
* Gets whether this attribute is collective.
*
* @return boolean Returns TRUE if this attribute is collective and FALSE otherwise.
* @deprecated use $this->is_collective
*/
public function getIsCollective(): bool
{
return $this->is_collective;
}
/**
* Gets whether this attribute is not modifiable by users.
*
* @return boolean Returns TRUE if this attribute is not modifiable by users.
* @deprecated use $this->is_no_user_modification
*/
public function getIsNoUserModification(): bool
{
return $this->is_no_user_modification;
}
/**
* Gets whether this attribute is single-valued. If this attribute only supports single values, TRUE
* is returned. If this attribute supports multiple values, FALSE is returned.
*
* @return boolean Returns TRUE if this attribute is single-valued or FALSE otherwise.
* @deprecated use class->is_single_value
*/
public function getIsSingleValue(): bool
{
return $this->is_single_value;
}
/**
* Gets this attribute's the maximum length. If no maximum is defined by the LDAP server, NULL is returned.
*
* @return int The maximum length (in characters) of this attribute or NULL if no maximum is specified.
* @deprecated use $this->max_length;
*/
public function getMaxLength()
{
return $this->max_length;
}
/**
* Gets this attribute's ordering specification.
*
* @return string
* @deprecated use $this->ordering
*/
public function getOrdering(): string
{
return $this->ordering;
}
/**
* Gets the list of "required by" objectClasses, that is the list of objectClasses
* which provide must have attribute.
*
* @return array An array of names of objectclasses (strings) which provide this attribute
*/
public function getRequiredByObjectClasses() {
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->required_by_object_classes);
return $this->required_by_object_classes;
}
/**
* Gets this attribute's substring matching specification
*
* @return string
* @deprecated use $this->sub_str_rule;
*/
public function getSubstr() {
return $this->sub_str_rule;
}
/**
* Gets this attribute's parent attribute (if any). If this attribute does not
* inherit from another attribute, NULL is returned.
*
* @return string
* @deprecated use $class->sup_attribute directly
*/
public function getSupAttribute() {
return $this->sup_attribute;
}
/**
* Gets this attribute's syntax OID. Differs from getSyntaxString() in that this
* function only returns the actual OID with any length specification removed.
* Ie, if the syntax string is "1.2.3.4{16}", this function only retruns
* "1.2.3.4".
*
* @return string The syntax OID string.
* @deprecated use $this->syntax_oid;
*/
public function getSyntaxOID()
{
return $this->syntax_oid;
}
/**
* Gets this attribute's raw syntax string (ie: "1.2.3.4{16}").
*
* @return string The raw syntax string
*/
public function getSyntaxString() {
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->syntax);
return $this->syntax;
}
/**
* Gets this attribute's type
*
* @return string The attribute's type.
* @deprecated use $this->type;
*/
public function getType()
{
return $this->type;
}
/**
* Gets this attribute's usage string as defined by the LDAP server
*
* @return string
* @deprecated use $this->usage
*/
public function getUsage()
{
return $this->usage;
}
/**
* Gets the list of "used in" objectClasses, that is the list of objectClasses
* which provide this attribute.
*
* @return Collection An array of names of objectclasses (strings) which provide this attribute
* @deprecated use $this->used_in_object_classes
*/
public function getUsedInObjectClasses(): Collection
{
return $this->used_in_object_classes;
}
/**
* Returns whether the specified attribute is an alias for this one (based on this attribute's alias list).
*
* @param string $attr_name The name of the attribute to check.
* @return boolean TRUE if the specified attribute is an alias for this one, or FALSE otherwise.
*/
public function isAliasFor($attr_name) {
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
debug_log('Entered (%%)',9,0,__FILE__,__LINE__,__METHOD__,$fargs);
foreach ($this->aliases as $alias_attr_name)
if (strcasecmp($alias_attr_name,$attr_name) == 0)
return TRUE;
return FALSE;
}
/**
* @return bool
* @deprecated use $this->forced_as_may
*/
public function isForceMay(): bool
{
return $this->forced_as_may;
}
/**
* Removes an attribute name from this attribute's alias array.
*
* @param string $alias The name of the attribute to remove.
*/
public function removeAlias(string $alias): void
{
if (($x=$this->aliases->search($alias)) !== FALSE)
$this->aliases->forget($x);
}
/**
* Given a list of object classes, determine if this is a required attribute
*
* @param Collection $oc List of objectclasses to compare.
* @return Collection
*/
public function required_by(Collection $oc): Collection
{
return $oc->diff($this->required_by_object_classes);
}
/**
* Sets this attribute's list of aliases.
*
* @param Collection $aliases The array of alias names (strings)
* @deprecated use $this->aliases =
*/
public function setAliases(Collection $aliases): void
{
$this->aliases = $aliases;
}
/**
* This function will mark this attribute as a forced MAY attribute
*/
public function setForceMay() {
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs);
$this->forced_as_may = TRUE;
}
/**
* Sets whether this attribute is single-valued.
*
* @param boolean $is
*/
public function setIsSingleValue(bool $is): void
{
$this->is_single_value = $is;
}
/**
* Sets this attribute's SUP attribute (ie, the attribute from which this attribute inherits).
*
* @param string $attr The name of the new parent (SUP) attribute
*/
public function setSupAttribute(string $attr): void
{
$this->sup_attribute = trim($attr);
}
/**
* Sets this attribute's type.
*
* @param string $type The new type.
*/
public function setType($type) {
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs);
$this->type = $type;
}
}

View File

@ -1,120 +0,0 @@
<?php
namespace App\Classes\LDAP\Schema;
use App\Exceptions\InvalidUsage;
/**
* Generic parent class for all schema items.
*
* A schema item is an ObjectClass, an AttributeBype, a MatchingRule, or a Syntax.
* All schema items have at least two things in common: An OID and a Description.
*/
abstract class Base {
// Record the LDAP String
private string $line;
// The schema item's name.
protected ?string $name = NULL;
// The OID of this schema item.
protected string $oid;
# The description of this schema item.
protected ?string $description = NULL;
// Boolean value indicating whether this objectClass is obsolete
private bool $is_obsolete = FALSE;
public function __construct(string $line)
{
$this->line = $line;
}
public function __get(string $key): mixed
{
switch ($key) {
case 'description': return $this->description;
case 'is_obsolete': return $this->is_obsolete;
case 'line': return $this->line;
case 'name': return $this->name;
case 'name_lc': return strtolower($this->name);
case 'oid': return $this->oid;
default:
throw new InvalidUsage('Unknown key:'.$key);
}
}
public function __isset(string $key): bool
{
return isset($this->{$key});
}
public function __toString(): string
{
return $this->name;
}
/**
* @return string
* @deprecated replace with $class->description
*/
public function getDescription(): string
{
return $this->description;
}
/**
* Gets whether this item is flagged as obsolete by the LDAP server.
*
* @deprecated replace with $this->is_obsolete
*/
public function getIsObsolete(): bool
{
return $this->is_obsolete;
}
/**
* Return the objects name.
*
* @param boolean $lower Return the name in lower case (default)
* @return string The name
* @deprecated use object->name
*/
public function getName(bool $lower=TRUE): string
{
return $lower ? strtolower($this->name) : $this->name;
}
/**
* Return the objects name.
*
* @return string The name
* @deprecated use object->oid
*/
public function getOID(): string
{
return $this->oid;
}
public function setDescription(string $desc): void
{
$this->description = $desc;
}
/**
* Sets this attribute's name.
*
* @param string $name The new name to give this attribute.
*/
public function setName($name): void
{
$this->name = $name;
}
public function setOID(string $oid): void
{
$this->oid = $oid;
}
}

View File

@ -1,79 +0,0 @@
<?php
namespace App\Classes\LDAP\Schema;
use Illuminate\Support\Facades\Log;
/**
* Represents an LDAP Syntax
*
* @package phpLDAPadmin
* @subpackage Schema
*/
final class LDAPSyntax extends Base {
// Is human readable?
private ?bool $is_not_human_readable = NULL;
// Binary transfer required?
private ?bool $binary_transfer_required = NULL;
/**
* Creates a new Syntax object from a raw LDAP syntax string.
*/
public function __construct(string $line) {
Log::debug(sprintf('Parsing LDAPSyntax [%s]',$line));
parent::__construct($line);
$strings = preg_split('/[\s,]+/',$line,-1,PREG_SPLIT_DELIM_CAPTURE);
for ($i=0; $i<count($strings); $i++) {
switch($strings[$i]) {
case '(':
case ')':
break;
case 'DESC':
do {
$this->description .= (strlen($this->description) ? ' ' : '').$strings[++$i];
} while (! preg_match("/\'$/s",$strings[$i]));
$this->description = preg_replace("/^\'(.*)\'$/",'$1',$this->description);
Log::debug(sprintf('- Case DESC returned (%s)',$this->description));
break;
case 'X-BINARY-TRANSFER-REQUIRED':
$this->binary_transfer_required = (str_replace("'",'',$strings[++$i]) === 'TRUE');
Log::debug(sprintf('- Case X-BINARY-TRANSFER-REQUIRED returned (%s)',$this->binary_transfer_required));
break;
case 'X-NOT-HUMAN-READABLE':
$this->is_not_human_readable = (str_replace("'",'',$strings[++$i]) === 'TRUE');
Log::debug(sprintf('- Case X-NOT-HUMAN-READABLE returned (%s)',$this->is_not_human_readable));
break;
default:
if (preg_match('/[\d\.]+/i',$strings[$i]) && ($i === 1)) {
$this->oid = $strings[$i];
Log::debug(sprintf('- Case default returned (%s)',$this->oid));
} elseif ($strings[$i])
Log::alert(sprintf('! Case default discovered a value NOT parsed (%s)',$strings[$i]),['line'=>$line]);
}
}
}
public function __get(string $key): mixed
{
switch ($key) {
case 'binary_transfer_required': return $this->binary_transfer_required;
case 'is_not_human_readable': return $this->is_not_human_readable;
default: return parent::__get($key);
}
}
}

View File

@ -1,142 +0,0 @@
<?php
namespace App\Classes\LDAP\Schema;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log;
/**
* Represents an LDAP MatchingRule
*
* @package phpLDAPadmin
* @subpackage Schema
*/
final class MatchingRule extends Base {
// This rule's syntax OID
private ?string $syntax = NULL;
// An array of attribute names who use this MatchingRule
private Collection $used_by_attrs;
/**
* Creates a new MatchingRule object from a raw LDAP MatchingRule string.
*/
function __construct(string $line) {
Log::debug(sprintf('Parsing MatchingRule [%s]',$line));
parent::__construct($line);
$strings = preg_split('/[\s,]+/',$line,-1,PREG_SPLIT_DELIM_CAPTURE);
// Init
$this->used_by_attrs = collect();
for ($i=0; $i<count($strings); $i++) {
switch ($strings[$i]) {
case '(':
case ')':
break;
case 'NAME':
if ($strings[$i+1] != '(') {
do {
$this->name .= (strlen($this->name) ? ' ' : '').$strings[++$i];
} while (! preg_match("/\'$/s",$strings[$i]));
} else {
$i++;
do {
$this->name .= (strlen($this->name) ? ' ' : '').$strings[++$i];
} while (! preg_match("/\'$/s",$strings[$i]));
do {
$i++;
} while (! preg_match('/\)+\)?/',$strings[$i]));
}
$this->name = preg_replace("/^\'/",'',$this->name);
$this->name = preg_replace("/\'$/",'',$this->name);
Log::debug(sprintf(sprintf('- Case NAME returned (%s)',$this->name)));
break;
case 'DESC':
do {
$this->description .= (strlen($this->description) ? ' ' : '').$strings[++$i];
} while (! preg_match("/\'$/s",$strings[$i]));
$this->description = preg_replace("/^\'(.*)\'$/",'$1',$this->description);
Log::debug(sprintf('- Case DESC returned (%s)',$this->description));
break;
case 'OBSOLETE':
$this->is_obsolete = TRUE;
Log::debug(sprintf('- Case OBSOLETE returned (%s)',$this->is_obsolete));
break;
case 'SYNTAX':
$this->syntax = $strings[++$i];
Log::debug(sprintf('- Case SYNTAX returned (%s)',$this->syntax));
break;
default:
if (preg_match('/[\d\.]+/i',$strings[$i]) && ($i === 1)) {
$this->oid = $strings[$i];
Log::debug(sprintf('- Case default returned (%s)',$this->oid));
} elseif ($strings[$i])
Log::alert(sprintf('! Case default discovered a value NOT parsed (%s)',$strings[$i]),['line'=>$line]);
}
}
}
public function __get(string $key): mixed
{
switch ($key) {
case 'syntax': return $this->syntax;
case 'used_by_attrs': return $this->used_by_attrs;
default: return parent::__get($key);
}
}
/**
* Adds an attribute name to the list of attributes who use this MatchingRule
*/
public function addUsedByAttr(string $name): void
{
$name = trim($name);
if ($this->used_by_attrs->search($name) === FALSE)
$this->used_by_attrs->push($name);
}
/**
* Gets an array of attribute names (strings) which use this MatchingRule
*
* @return array The array of attribute names (strings).
* @deprecated use $this->used_by_attrs
*/
public function getUsedByAttrs()
{
return $this->used_by_attrs;
}
/**
* Sets the list of used_by_attrs to the array specified by $attrs;
*
* @param Collection $attrs The array of attribute names (strings) which use this MatchingRule
*/
public function setUsedByAttrs(Collection $attrs): void
{
$this->used_by_attrs = $attrs;
}
}

View File

@ -1,99 +0,0 @@
<?php
namespace App\Classes\LDAP\Schema;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log;
/**
* Represents an LDAP schema matchingRuleUse entry
*
* @package phpLDAPadmin
* @subpackage Schema
*/
final class MatchingRuleUse extends Base {
// An array of attribute names who use this MatchingRule
private Collection $used_by_attrs;
function __construct(string $line) {
Log::debug(sprintf('Parsing MatchingRuleUse [%s]',$line));
parent::__construct($line);
$strings = preg_split('/[\s,]+/',$line,-1,PREG_SPLIT_DELIM_CAPTURE);
// Init
$this->used_by_attrs = collect();
for ($i=0; $i<count($strings); $i++) {
switch ($strings[$i]) {
case '(':
case ')':
break;
case 'NAME':
if ($strings[$i+1] != '(') {
do {
$this->name .= (strlen($this->name) ? ' ' : '').$strings[++$i];
} while (! preg_match("/\'$/s",$strings[$i]));
} else {
$i++;
do {
$this->name .= (strlen($this->name) ? ' ' : '').$strings[++$i];
} while (! preg_match("/\'$/s",$strings[$i]));
do {
$i++;
} while (! preg_match('/\)+\)?/',$strings[$i]));
}
$this->name = preg_replace("/^\'(.*)\'$/",'$1',$this->name);
Log::debug(sprintf(sprintf('- Case NAME returned (%s)',$this->name)));
break;
case 'APPLIES':
if ($strings[$i+1] != '(') {
// Has a single attribute name
$this->used_by_attrs = collect($strings[++$i]);
} else {
// Has multiple attribute names
while ($strings[++$i] != ')') {
$new_attr = $strings[++$i];
$new_attr = preg_replace("/^\'(.*)\'$/",'$1',$new_attr);
$this->used_by_attrs->push($new_attr);
}
}
Log::debug(sprintf('- Case APPLIES returned (%s)',$this->used_by_attrs->join(',')));
break;
default:
if (preg_match('/[\d\.]+/i',$strings[$i]) && ($i === 1)) {
$this->oid = $strings[$i];
Log::debug(sprintf('- Case default returned (%s)',$this->oid));
} elseif ($strings[$i])
Log::alert(sprintf('! Case default discovered a value NOT parsed (%s)',$strings[$i]),['line'=>$line]);
}
}
}
/**
* Gets an array of attribute names (strings) which use this MatchingRuleUse object.
*
* @return array The array of attribute names (strings).
* @deprecated use $this->used_by_attrs
*/
public function getUsedByAttrs()
{
return $this->used_by_attrs;
}
}

View File

@ -1,540 +0,0 @@
<?php
namespace App\Classes\LDAP\Schema;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log;
use App\Classes\LDAP\Server;
use App\Exceptions\InvalidUsage;
use App\Ldap\Entry;
/**
* Represents an LDAP Schema objectClass
*
* @package phpLDAPadmin
* @subpackage Schema
*/
final class ObjectClass extends Base {
// The server ID that this objectclass belongs to.
private Server $server;
// Array of objectClass names from which this objectClass inherits
private Collection $sup_classes;
// One of STRUCTURAL, ABSTRACT, or AUXILIARY
private int $type;
// Arrays of attribute names that this objectClass requires
private Collection $must_attrs;
// Arrays of attribute names that this objectClass allows, but does not require
private Collection $may_attrs;
// Arrays of attribute names that this objectClass has been forced to MAY attrs, due to configuration
private Collection $may_force;
// Array of objectClasses which inherit from this one
private Collection $child_objectclasses;
private bool $is_obsolete;
/* ObjectClass Types */
private const OC_STRUCTURAL = 0x01;
private const OC_ABSTRACT = 0x02;
private const OC_AUXILIARY = 0x03;
/**
* Creates a new ObjectClass object given a raw LDAP objectClass string.
*
* eg: ( 2.5.6.0 NAME 'top' DESC 'top of the superclass chain' ABSTRACT MUST objectClass )
*/
public function __construct(string $line,Server $server)
{
parent::__construct($line);
Log::debug(sprintf('Parsing ObjectClass [%s]',$line));
$strings = preg_split('/[\s,]+/',$line,-1,PREG_SPLIT_DELIM_CAPTURE);
// Init
$this->server = $server;
$this->may_attrs = collect();
$this->may_force = collect();
$this->must_attrs = collect();
$this->sup_classes = collect();
$this->child_objectclasses = collect();
for ($i=0; $i < count($strings); $i++) {
switch ($strings[$i]) {
case '(':
case ')':
break;
case 'NAME':
if ($strings[$i+1] != '(') {
do {
$this->name .= (strlen($this->name) ? ' ' : '').$strings[++$i];
} while (! preg_match('/\'$/s',$strings[$i]));
} else {
$i++;
do {
$this->name .= (strlen($this->name) ? ' ' : '').$strings[++$i];
} while (! preg_match('/\'$/s',$strings[$i]));
do {
$i++;
} while (! preg_match('/\)+\)?/',$strings[$i]));
}
$this->name = preg_replace("/^\'(.*)\'$/",'$1',$this->name);
Log::debug(sprintf(sprintf('- Case NAME returned (%s)',$this->name)));
break;
case 'DESC':
do {
$this->description .= (strlen($this->description) ? ' ' : '').$strings[++$i];
} while (! preg_match('/\'$/s',$strings[$i]));
$this->description = preg_replace("/^\'(.*)\'$/",'$1',$this->description);
Log::debug(sprintf('- Case DESC returned (%s)',$this->description));
break;
case 'OBSOLETE':
$this->is_obsolete = TRUE;
Log::debug(sprintf('- Case OBSOLETE returned (%s)',$this->is_obsolete));
break;
case 'SUP':
if ($strings[$i+1] != '(') {
$this->sup_classes->push(preg_replace("/'/",'',$strings[++$i]));
} else {
$i++;
do {
$i++;
if ($strings[$i] != '$')
$this->sup_classes->push(preg_replace("/'/",'',$strings[$i]));
} while (! preg_match('/\)+\)?/',$strings[$i+1]));
}
Log::debug(sprintf('- Case SUP returned (%s)',$this->sup_classes->join(',')));
break;
case 'ABSTRACT':
$this->type = self::OC_ABSTRACT;
Log::debug(sprintf('- Case ABSTRACT returned (%s)',$this->type));
break;
case 'STRUCTURAL':
$this->type = self::OC_STRUCTURAL;
Log::debug(sprintf('- Case STRUCTURAL returned (%s)',$this->type));
break;
case 'AUXILIARY':
$this->type = self::OC_AUXILIARY;
Log::debug(sprintf('- Case AUXILIARY returned (%s)',$this->type));
break;
case 'MUST':
$attrs = collect();
$i = $this->parseList(++$i,$strings,$attrs);
Log::debug(sprintf('= parseList returned %d (%s)',$i,$attrs->join(',')));
foreach ($attrs as $string) {
$attr = new ObjectClassAttribute($string,$this->name);
if ($server->isForceMay($attr->getName())) {
$this->may_force->push($attr);
$this->may_attrs->push($attr);
} else
$this->must_attrs->push($attr);
}
Log::debug(sprintf('- Case MUST returned (%s) (%s)',$this->must_attrs->join(','),$this->may_force->join(',')));
break;
case 'MAY':
$attrs = collect();
$i = $this->parseList(++$i,$strings,$attrs);
Log::debug(sprintf('parseList returned %d (%s)',$i,$attrs->join(',')));
foreach ($attrs as $string) {
$attr = new ObjectClassAttribute($string,$this->name);
$this->may_attrs->push($attr);
}
Log::debug(sprintf('- Case MAY returned (%s)',$this->may_attrs->join(',')));
break;
default:
if (preg_match('/[\d\.]+/i',$strings[$i]) && ($i === 1)) {
$this->oid = $strings[$i];
Log::debug(sprintf('- Case default returned (%s)',$this->oid));
} elseif ($strings[$i])
Log::alert(sprintf('! Case default discovered a value NOT parsed (%s)',$strings[$i]),['line'=>$line]);
}
}
}
public function __get(string $key): mixed
{
switch ($key) {
case 'attributes':
return $this->getAllAttrs();
case 'sup':
return $this->sup_classes;
case 'type_name':
switch ($this->type) {
case self::OC_STRUCTURAL: return 'Structural';
case self::OC_ABSTRACT: return 'Abstract';
case self::OC_AUXILIARY: return 'Auxiliary';
default:
throw new InvalidUsage('Unknown ObjectClass Type: '.$this->type);
}
default: return parent::__get($key);
}
}
/**
* Return a list of attributes that this objectClass provides
*
* @return Collection
*/
public function getAllAttrs(): Collection
{
return $this->getMustAttrs()->merge($this->getMayAttrs());
}
/**
* Adds an objectClass to the list of objectClasses that inherit
* from this objectClass.
*
* @param String $name The name of the objectClass to add
*/
public function addChildObjectClass(string $name): void
{
if ($this->child_objectclasses->search($name) === FALSE) {
$this->child_objectclasses->push($name);
}
}
/**
* Returns the array of objectClass names which inherit from this objectClass.
*
* @return Collection Names of objectClasses which inherit from this objectClass.
* @deprecated use $this->child_objectclasses
*/
public function getChildObjectClasses(): Collection
{
return $this->child_objectclasses;
}
/**
* Behaves identically to addMustAttrs, but it operates on the MAY
* attributes of this objectClass.
*
* @param array $attr An array of attribute names (strings) to add.
*/
private function addMayAttrs(array $attr): void
{
if (! is_array($attr) || ! count($attr))
return;
$this->may_attrs = $this->may_attrs->merge($attr)->unique();
}
/**
* Adds the specified array of attributes to this objectClass' list of
* MUST attributes. The resulting array of must attributes will contain
* unique members.
*
* @param array $attr An array of attribute names (strings) to add.
*/
private function addMustAttrs(array $attr): void
{
if (! is_array($attr) || ! count($attr))
return;
$this->must_attrs = $this->must_attrs->merge($attr)->unique();
}
/**
* @return Collection
* @deprecated use $this->may_force
*/
public function getForceMayAttrs(): Collection
{
return $this->may_force;
}
/**
* Gets an array of AttributeType objects that entries of this ObjectClass may define.
* This differs from getMayAttrNames in that it returns an array of AttributeType objects
*
* @param bool $parents Also get the may attrs of our parents.
* @return Collection The array of allowed AttributeType objects.
*
* @throws InvalidUsage
* @see getMustAttrNames
* @see getMustAttrs
* @see getMayAttrNames
* @see AttributeType
*/
public function getMayAttrs(bool $parents=FALSE): Collection
{
// If we dont need our parents, then we'll just return ours.
if (! $parents)
return $this->may_attrs->sortBy(function($item) { return strtolower($item->name.$item->source); });
$attrs = $this->may_attrs;
foreach ($this->getParents() as $object_class) {
$sc = $this->server->schema('objectclasses',$object_class);
$attrs = $attrs->merge($sc->getMayAttrs($parents));
}
// Remove any duplicates
$attrs = $attrs->unique(function($item) { return $item->name; });
// Return a sorted list
return $attrs->sortBy(function($item) { return strtolower($item->name.$item->source); });
}
/**
* Gets an array of attribute names (strings) that entries of this ObjectClass must define.
* This differs from getMayAttrs in that it returns an array of strings rather than
* array of AttributeType objects
*
* @param bool $parents An array of ObjectClass objects to use when traversing
* the inheritance tree. This presents some what of a bootstrapping problem
* as we must fetch all objectClasses to determine through inheritance which
* attributes this objectClass provides.
* @return Collection The array of allowed attribute names (strings).
*
* @throws InvalidUsage
* @see getMustAttrs
* @see getMayAttrs
* @see getMustAttrNames
*/
public function getMayAttrNames(bool $parents=FALSE): Collection
{
return $this->getMayAttrs($parents)->ppluck('name');
}
/**
* Gets an array of AttributeType objects that entries of this ObjectClass must define.
* This differs from getMustAttrNames in that it returns an array of AttributeType objects
*
* @param bool $parents Also get the must attrs of our parents.
* @return Collection The array of required AttributeType objects.
*
* @throws InvalidUsage
* @see getMustAttrNames
* @see getMayAttrs
* @see getMayAttrNames
*/
public function getMustAttrs(bool $parents=FALSE): Collection
{
// If we dont need our parents, then we'll just return ours.
if (! $parents)
return $this->must_attrs->sortBy(function($item) { return strtolower($item->name.$item->source); });
$attrs = $this->must_attrs;
foreach ($this->getParents() as $object_class) {
$sc = $this->server->schema('objectclasses',$object_class);
$attrs = $attrs->merge($sc->getMustAttrs($parents));
}
// Remove any duplicates
$attrs = $attrs->unique(function($item) { return $item->name; });
// Return a sorted list
return $attrs->sortBy(function($item) { return strtolower($item->name.$item->source); });
}
/**
* Gets an array of attribute names (strings) that entries of this ObjectClass must define.
* This differs from getMustAttrs in that it returns an array of strings rather than
* array of AttributeType objects
*
* @param bool $parents An array of ObjectClass objects to use when traversing
* the inheritance tree. This presents some what of a bootstrapping problem
* as we must fetch all objectClasses to determine through inheritance which
* attributes this objectClass provides.
* @return Collection The array of allowed attribute names (strings).
*
* @throws InvalidUsage
* @see getMustAttrs
* @see getMayAttrs
* @see getMayAttrNames
*/
public function getMustAttrNames(bool $parents=FALSE): Collection
{
return $this->getMustAttrs($parents)->ppluck('name');
}
/**
* This will return all our parent ObjectClass Objects
*/
public function getParents(): Collection
{
// If the only class is 'top', then we have no more parents
if (($this->sup_classes->count() === 1) && (strtolower($this->sup_classes->first()) === 'top'))
return collect();
$result = collect();
foreach ($this->sup_classes as $object_class) {
$result->push($object_class);
$oc = $this->server->schema('objectclasses',$object_class);
if ($oc)
$result = $result->merge($oc->getParents());
}
return $result;
}
/**
* Gets the objectClass names from which this objectClass inherits.
*
* @return Collection An array of objectClass names (strings)
* @deprecated use $this->sup_classes;
*/
public function getSupClasses(): Collection
{
return $this->sup_classes;
}
/**
* Gets the type of this objectClass: STRUCTURAL, ABSTRACT, or AUXILIARY.
*
* @deprecated use $this->type_name
*/
public function getType()
{
return $this->type;
}
/**
* Determine if an array is listed in the may_force attrs
*/
public function isForceMay(string $attr): bool
{
return $this->may_force->ppluck('name')->contains($attr);
}
/**
* Return if this objectClass is related to $oclass
*
* @param array $oclass ObjectClasses that this attribute may be related to
* @return bool
* @throws InvalidUsage
*/
public function isRelated(array $oclass): bool
{
// If I am in the array, we'll just return false
if (in_array_ignore_case($this->name,$oclass))
return FALSE;
foreach ($oclass as $object_class) {
$oc = $this->server->schema('objectclasses',$object_class);
if ($oc->isStructural() && in_array_ignore_case($this->name,$oc->getParents()))
return TRUE;
}
return FALSE;
}
public function isStructural(): bool
{
return $this->type === self::OC_STRUCTURAL;
}
/**
* Parse an LDAP schema list
*
* A list starts with a ( followed by a list of attributes separated by $ terminated by )
* The first token can therefore be a ( or a (NAME or a (NAME)
* The last token can therefore be a ) or NAME)
* The last token may be terminated by more than one bracket
*/
private function parseList(int $i,array $strings,Collection &$attrs): int
{
$string = $strings[$i];
if (! preg_match('/^\(/',$string)) {
// A bareword only - can be terminated by a ) if the last item
if (preg_match('/\)+$/',$string))
$string = preg_replace('/\)+$/','',$string);
$attrs->push($string);
} elseif (preg_match('/^\(.*\)$/',$string)) {
$string = preg_replace('/^\(/','',$string);
$string = preg_replace('/\)+$/','',$string);
$attrs->push($string);
} else {
// Handle the opening cases first
if ($string === '(') {
$i++;
} elseif (preg_match('/^\(./',$string)) {
$string = preg_replace('/^\(/','',$string);
$attrs->push($string);
$i++;
}
// Token is either a name, a $ or a ')'
// NAME can be terminated by one or more ')'
while (! preg_match('/\)+$/',$strings[$i])) {
$string = $strings[$i];
if ($string === '$') {
$i++;
continue;
}
if (preg_match('/\)$/',$string))
$string = preg_replace('/\)+$/','',$string);
else
$i++;
$attrs->push($string);
}
}
$attrs = $attrs->sort();
return $i;
}
}

View File

@ -1,41 +0,0 @@
<?php
namespace App\Classes\LDAP\Schema;
/**
* A simple class for representing AttributeTypes used only by the ObjectClass class.
*
* Users should never instantiate this class. It represents an attribute internal to
* an ObjectClass. If PHP supported inner-classes and variable permissions, this would
* be interior to class ObjectClass and flagged private. The reason this class is used
* and not the "real" class AttributeType is because this class supports the notion of
* a "source" objectClass, meaning that it keeps track of which objectClass originally
* specified it. This class is therefore used by the class ObjectClass to determine
* inheritance.
*/
final class ObjectClassAttribute extends Base {
// This Attribute's root.
private string $source;
/**
* Creates a new ObjectClassAttribute with specified name and source objectClass.
*
* @param string $name the name of the new attribute.
* @param string $source the name of the ObjectClass which specifies this attribute.
*/
public function __construct($name,$source)
{
$this->name = $name;
$this->source = $source;
}
public function __get(string $key): mixed
{
switch ($key) {
case 'source':
return $this->source;
default: return parent::__get($key);
}
}
}

View File

@ -1,551 +0,0 @@
<?php
namespace App\Classes\LDAP;
use Carbon\Carbon;
use Exception;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Cookie;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Session;
use LdapRecord\LdapRecordException;
use LdapRecord\Models\Model;
use LdapRecord\Query\Collection as LDAPCollection;
use LdapRecord\Query\ObjectNotFoundException;
use App\Classes\LDAP\Schema\{AttributeType,Base,LDAPSyntax,MatchingRule,MatchingRuleUse,ObjectClass};
use App\Exceptions\InvalidUsage;
use App\Ldap\Entry;
final class Server
{
// This servers schema objectclasses
private Collection $attributetypes;
private Collection $ldapsyntaxes;
private Collection $matchingrules;
private Collection $matchingruleuse;
private Collection $objectclasses;
// Valid items that can be fetched
public const schema_types = [
'objectclasses',
'attributetypes',
'ldapsyntaxes',
'matchingrules',
];
public function __get(string $key): mixed
{
switch ($key) {
case 'attributetypes': return $this->attributetypes;
case 'ldapsyntaxes': return $this->ldapsyntaxes;
case 'matchingrules': return $this->matchingrules;
case 'objectclasses': return $this->objectclasses;
default:
throw new Exception('Unknown key:'.$key);
}
}
/* STATIC METHODS */
/**
* Gets the root DN of the specified LDAPServer, or throws an exception if it
* can't find it.
*
* @param null $connection Return a collection of baseDNs
* @param bool $objects Return a collection of Entry Models
* @return Collection
* @throws ObjectNotFoundException
* @testedin GetBaseDNTest::testBaseDNExists();
* @todo Need to allow for the scenario if the baseDN is not readable by ACLs
*/
public static function baseDNs($connection=NULL,bool $objects=TRUE): Collection
{
$cachetime = Carbon::now()->addSeconds(Config::get('ldap.cache.time'));
try {
$base = self::rootDSE($connection,$cachetime);
/**
* LDAP Error Codes:
* https://ldap.com/ldap-result-code-reference/
* + success 0
* + operationsError 1
* + protocolError 2
* + timeLimitExceeded 3
* + sizeLimitExceeded 4
* + compareFalse 5
* + compareTrue 6
* + authMethodNotSupported 7
* + strongerAuthRequired 8
* + referral 10
* + adminLimitExceeded 11
* + unavailableCriticalExtension 12
* + confidentialityRequired 13
* + saslBindInProgress 14
* + noSuchAttribute 16
* + undefinedAttributeType 17
* + inappropriateMatching 18
* + constraintViolation 19
* + attributeOrValueExists 20
* + invalidAttributeSyntax 21
* + noSuchObject 32
* + aliasProblem 33
* + invalidDNSyntax 34
* + isLeaf 35
* + aliasDereferencingProblem 36
* + inappropriateAuthentication 48
* + invalidCredentials 49
* + insufficientAccessRights 50
* + busy 51
* + unavailable 52
* + unwillingToPerform 53
* + loopDetect 54
* + sortControlMissing 60
* + offsetRangeError 61
* + namingViolation 64
* + objectClassViolation 65
* + notAllowedOnNonLeaf 66
* + notAllowedOnRDN 67
* + entryAlreadyExists 68
* + objectClassModsProhibited 69
* + resultsTooLarge 70
* + affectsMultipleDSAs 71
* + virtualListViewError or controlError 76
* + other 80
* + serverDown 81
* + localError 82
* + encodingError 83
* + decodingError 84
* + timeout 85
* + authUnknown 86
* + filterError 87
* + userCanceled 88
* + paramError 89
* + noMemory 90
* + connectError 91
* + notSupported 92
* + controlNotFound 93
* + noResultsReturned 94
* + moreResultsToReturn 95
* + clientLoop 96
* + referralLimitExceeded 97
* + invalidResponse 100
* + ambiguousResponse 101
* + tlsNotSupported 112
* + intermediateResponse 113
* + unknownType 114
* + canceled 118
* + noSuchOperation 119
* + tooLate 120
* + cannotCancel 121
* + assertionFailed 122
* + authorizationDenied 123
* + e-syncRefreshRequired 4096
* + noOperation 16654
*
* LDAP Tag Codes:
* + A client bind operation 97
* + The entry for which you were searching 100
* + The result from a search operation 101
* + The result from a modify operation 103
* + The result from an add operation 105
* + The result from a delete operation 107
* + The result from a modify DN operation 109
* + The result from a compare operation 111
* + A search reference when the entry you perform your search on holds a referral to the entry you require.
* + Search references are expressed in terms of a referral.
* 115
* + A result from an extended operation 120
*/
// If we cannot get to our LDAP server we'll head straight to the error page
} catch (LdapRecordException $e) {
switch ($e->getDetailedError()->getErrorCode()) {
case 49:
// Since we failed authentication, we should delete our auth cookie
if (Cookie::has('password_encrypt')) {
Log::alert('Clearing user credentials and logging out');
Cookie::queue(Cookie::forget('password_encrypt'));
Cookie::queue(Cookie::forget('username_encrypt'));
Session::invalidate();
}
abort(401,$e->getDetailedError()->getErrorMessage());
default:
abort(597,$e->getDetailedError()->getErrorMessage());
}
}
if (! $objects)
return collect($base->namingcontexts);
/**
* @note While we are caching our baseDNs, it seems if we have more than 1,
* our caching doesnt generate a hit on a subsequent call to this function (before the cache expires).
* IE: If we have 5 baseDNs, it takes 5 calls to this function to case them all.
* @todo Possibly a bug wtih ldaprecord, so need to investigate
*/
$result = collect();
foreach ($base->namingcontexts as $dn) {
$result->push((new Entry)->cache($cachetime)->findOrFail($dn));
}
return $result;
}
/**
* Obtain the rootDSE for the server, that gives us server information
*
* @param null $connection
* @return Entry|null
* @throws ObjectNotFoundException
* @testedin TranslateOidTest::testRootDSE();
*/
public static function rootDSE($connection=NULL,Carbon $cachetime=NULL): ?Model
{
$e = new Entry;
return Entry::on($connection ?? $e->getConnectionName())
->cache($cachetime)
->in(NULL)
->read()
->select(['+'])
->whereHas('objectclass')
->firstOrFail();
}
/**
* Get the Schema DN
*
* @param $connection
* @return string
* @throws ObjectNotFoundException
*/
public static function schemaDN($connection=NULL): string
{
$cachetime = Carbon::now()->addSeconds(Config::get('ldap.cache.time'));
return collect(self::rootDSE($connection,$cachetime)->subschemasubentry)->first();
}
/**
* Query the server for a DN and return its children and if those children have children.
*
* @param string $dn
* @return LDAPCollection|NULL
*/
public function children(string $dn): ?LDAPCollection
{
return ($x=(new Entry)
->query()
->cache(Carbon::now()->addSeconds(Config::get('ldap.cache.time')))
->select(['*','hassubordinates'])
->setDn($dn)
->list()
->get()) ? $x : NULL;
}
/**
* Fetch a DN from the server
*
* @param string $dn
* @param array $attrs
* @return Entry|null
*/
public function fetch(string $dn,array $attrs=['*','+']): ?Entry
{
return ($x=(new Entry)
->query()
->cache(Carbon::now()->addSeconds(Config::get('ldap.cache.time')))
->select($attrs)
->find($dn)) ? $x : NULL;
}
/**
* This function determines if the specified attribute is contained in the force_may list
* as configured in config.php.
*
* @return boolean True if the specified attribute is configured to be force as a may attribute
*/
public function isForceMay($attr_name): bool
{
return in_array($attr_name,config('pla.force_may',[]));
}
/**
* Does this server support RFC3666 language tags
* OID: 1.3.6.1.4.1.4203.1.5.4
*
* @return bool
* @throws ObjectNotFoundException
*/
public function isLanguageTags(): bool
{
return in_array('1.3.6.1.4.1.4203.1.5.4',$this->rootDSE()->supportedfeatures);
}
/**
* Return the server's schema
*
* @param string $item Schema Item to Fetch
* @param string|null $key
* @return Collection|Base|NULL
* @throws InvalidUsage
*/
public function schema(string $item,string $key=NULL): Collection|Base|NULL
{
// Ensure our item to fetch is lower case
$item = strtolower($item);
if ($key)
$key = strtolower($key);
// This error message is not localized as only developers should ever see it
if (! in_array($item,self::schema_types))
throw new InvalidUsage('Invalid request to fetch schema: '.$item);
$result = Cache::remember('schema'.$item,config('ldap.cache.time'),function() use ($item) {
// First pass if we have already retrieved the schema item
switch ($item) {
case 'attributetypes':
if (isset($this->attributetypes))
return $this->attributetypes;
else
$this->attributetypes = collect();
break;
case 'ldapsyntaxes':
if (isset($this->ldapsyntaxes))
return $this->ldapsyntaxes;
else
$this->ldapsyntaxes = collect();
break;
case 'matchingrules':
if (isset($this->matchingrules))
return $this->matchingrules;
else
$this->matchingrules = collect();
break;
/*
case 'matchingruleuse':
if (isset($this->matchingruleuse))
return is_null($key) ? $this->matchingruleuse : $this->matchingruleuse->get($key);
else
$this->matchingruleuse = collect();
break;
*/
case 'objectclasses':
if (isset($this->objectclasses))
return $this->objectclasses;
else
$this->objectclasses = collect();
break;
// Shouldnt get here
default:
throw new InvalidUsage('Invalid request to fetch schema: '.$item);
}
// Try to get the schema DN from the specified entry.
$schema_dn = $this->schemaDN();
$schema = $this->fetch($schema_dn);
switch ($item) {
case 'attributetypes':
Log::debug('Attribute Types');
// build the array of attribueTypes
//$syntaxes = $this->SchemaSyntaxes($dn);
foreach ($schema->{$item} as $line) {
if (is_null($line) || ! strlen($line))
continue;
$o = new AttributeType($line);
$this->attributetypes->put($o->name_lc,$o);
/*
if (isset($syntaxes[$attr->getSyntaxOID()])) {
$syntax = $syntaxes[$attr->getSyntaxOID()];
$attr->setType($syntax->getDescription());
}
$this->attributetypes[$attr->getName()] = $attr;
*/
/**
* bug 856832: create an entry in the $attrs_oid array too. This
* will be a ref to the $attrs entry for maintenance and performance
* reasons
*/
//$attrs_oid[$attr->getOID()] = &$attrs[$attr->getName()];
}
// go back and add data from aliased attributeTypes
foreach ($this->attributetypes as $o) {
/* foreach of the attribute's aliases, create a new entry in the attrs array
* with its name set to the alias name, and all other data copied.*/
if ($o->aliases->count()) {
Log::debug(sprintf('\ Attribute [%s] has the following aliases [%s]',$o->name,$o->aliases->join(',')));
foreach ($o->aliases as $alias) {
$new_attr = clone $o;
$new_attr->setName($alias);
$new_attr->addAlias($o->name);
$new_attr->removeAlias($alias);
$this->attributetypes->put(strtolower($alias),$new_attr);
}
}
}
// Now go through and reference the parent/child relationships
foreach ($this->attributetypes as $o)
if ($o->sup_attribute) {
$parent = strtolower($o->sup_attribute);
if ($this->attributetypes->has($parent) !== FALSE)
$this->attributetypes[$parent]->addChild($o->name);
}
// go through any children and add details if the child doesnt have them (ie, cn inherits name)
// @todo This doesnt traverse children properly, so children of children may not get the settings they should
foreach ($this->attributetypes as $parent) {
foreach ($parent->children as $child) {
$child = strtolower($child);
/* only overwrite the child's SINGLE-VALUE property if the parent has it set, and the child doesnt
* (note: All LDAP attributes default to multi-value if not explicitly set SINGLE-VALUE) */
if (! is_null($parent->is_single_value) && is_null($this->attributetypes[$child]->is_single_value))
$this->attributetypes[$child]->setIsSingleValue($parent->is_single_value);
}
}
// Add the used in and required_by values.
foreach ($this->schema('objectclasses') as $object_class) {
$must_attrs = $object_class->getMustAttrNames();
$may_attrs = $object_class->getMayAttrNames();
$oclass_attrs = $must_attrs->merge($may_attrs)->unique();
// Add Used In.
foreach ($oclass_attrs as $attr_name)
if ($this->attributetypes->has(strtolower($attr_name)))
$this->attributetypes[strtolower($attr_name)]->addUsedInObjectClass($object_class->name);
// Add Required By.
foreach ($must_attrs as $attr_name)
if ($this->attributetypes->has(strtolower($attr_name)))
$this->attributetypes[strtolower($attr_name)]->addRequiredByObjectClass($object_class->name);
// Force May
foreach ($object_class->getForceMayAttrs() as $attr_name)
if ($this->attributetypes->has(strtolower($attr_name->name)))
$this->attributetypes[strtolower($attr_name->name)]->setForceMay();
}
return $this->attributetypes;
case 'ldapsyntaxes':
Log::debug('LDAP Syntaxes');
foreach ($schema->{$item} as $line) {
if (is_null($line) || ! strlen($line))
continue;
$o = new LDAPSyntax($line);
$this->ldapsyntaxes->put(strtolower($o->oid),$o);
}
return $this->ldapsyntaxes;
case 'matchingrules':
Log::debug('Matching Rules');
$this->matchingruleuse = collect();
foreach ($schema->{$item} as $line) {
if (is_null($line) || ! strlen($line))
continue;
$o = new MatchingRule($line);
$this->matchingrules->put($o->name_lc,$o);
}
/*
* For each MatchingRuleUse entry, add the attributes who use it to the
* MatchingRule in the $rules array.
*/
if ($schema->matchingruleuse) {
foreach ($schema->matchingruleuse as $line) {
if (is_null($line) || ! strlen($line))
continue;
$o = new MatchingRuleUse($line);
$this->matchingruleuse->put($o->name_lc,$o);
if ($this->matchingrules->has($o->name_lc) !== FALSE)
$this->matchingrules[$o->name_lc]->setUsedByAttrs($o->getUsedByAttrs());
}
} else {
/* No MatchingRuleUse entry in the subschema, so brute-forcing
* the reverse-map for the "$rule->getUsedByAttrs()" data.*/
foreach ($this->schema('attributetypes') as $attr) {
$rule_key = strtolower($attr->getEquality());
if ($this->matchingrules->has($rule_key) !== FALSE)
$this->matchingrules[$rule_key]->addUsedByAttr($attr->name);
}
}
return $this->matchingrules;
case 'objectclasses':
Log::debug('Object Classes');
foreach ($schema->{$item} as $line) {
if (is_null($line) || ! strlen($line))
continue;
$o = new ObjectClass($line,$this);
$this->objectclasses->put($o->name_lc,$o);
}
// Now go through and reference the parent/child relationships
foreach ($this->objectclasses as $o)
foreach ($o->getSupClasses() as $parent) {
$parent = strtolower($parent);
if ($this->objectclasses->has($parent) !== FALSE)
$this->objectclasses[$parent]->addChildObjectClass($o->name);
}
return $this->objectclasses;
}
});
return is_null($key) ? $result : $result->get($key);
}
/**
* Given an OID, return the ldapsyntax for the OID
*
* @param string $oid
* @return LDAPSyntax|null
* @throws InvalidUsage
*/
public function schemaSyntaxName(string $oid): ?LDAPSyntax
{
return $this->schema('ldapsyntaxes',$oid);
}
}

View File

@ -1,41 +0,0 @@
<?php
namespace App\Console;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
class Kernel extends ConsoleKernel
{
/**
* The Artisan commands provided by your application.
*
* @var array
*/
protected $commands = [
//
];
/**
* Define the application's command schedule.
*
* @param \Illuminate\Console\Scheduling\Schedule $schedule
* @return void
*/
protected function schedule(Schedule $schedule)
{
// $schedule->command('inspire')->hourly();
}
/**
* Register the commands for the application.
*
* @return void
*/
protected function commands()
{
$this->load(__DIR__.'/Commands');
require base_path('routes/console.php');
}
}

View File

@ -1,50 +0,0 @@
<?php
namespace App\Exceptions;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Throwable;
class Handler extends ExceptionHandler
{
/**
* A list of exception types with their corresponding custom log levels.
*
* @var array<class-string<\Throwable>, \Psr\Log\LogLevel::*>
*/
protected $levels = [
//
];
/**
* A list of the exception types that are not reported.
*
* @var array<int, class-string<\Throwable>>
*/
protected $dontReport = [
//
];
/**
* A list of the inputs that are never flashed to the session on validation exceptions.
*
* @var array<int, string>
*/
protected $dontFlash = [
'current_password',
'password',
'password_confirmation',
];
/**
* Register the exception handling callbacks for the application.
*
* @return void
*/
public function register()
{
$this->reportable(function (Throwable $e) {
//
});
}
}

View File

@ -1,7 +0,0 @@
<?php
namespace App\Exceptions\Import;
use Exception;
class AttributeException extends Exception {}

View File

@ -1,7 +0,0 @@
<?php
namespace App\Exceptions\Import;
use Exception;
class GeneralException extends Exception {}

View File

@ -1,7 +0,0 @@
<?php
namespace App\Exceptions\Import;
use Exception;
class ObjectExistsException extends Exception {}

View File

@ -1,7 +0,0 @@
<?php
namespace App\Exceptions\Import;
use Exception;
class VersionException extends Exception {}

View File

@ -1,10 +0,0 @@
<?php
namespace App\Exceptions;
use Exception;
class InvalidUsage extends Exception
{
//
}

View File

@ -1,85 +0,0 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Crypt;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Collection;
use App\Classes\LDAP\Server;
class APIController extends Controller
{
/**
* Get the LDAP server BASE DNs
*
* @return Collection
* @throws LdapRecord\Query\ObjectNotFoundException
*/
public function bases(): Collection
{
$base = Server::baseDNs() ?: collect();
return $base->transform(function($item) {
return [
'title'=>$item->getRdn(),
'item'=>$item->getDNSecure(),
'lazy'=>TRUE,
'icon'=>'fa-fw fas fa-sitemap',
'tooltip'=>$item->getDn(),
];
});
}
/**
* @param Request $request
* @return Collection
*/
public function children(Request $request): Collection
{
$levels = $request->query('depth',1);
$dn = Crypt::decryptString($request->query('key'));
Log::debug(sprintf('%s: Query [%s] - Levels [%d]',__METHOD__,$dn,$levels));
return (config('server'))
->children($dn)
->transform(function($item) {
return [
'title'=>$item->getRdn(),
'item'=>$item->getDNSecure(),
'icon'=>$item->icon(),
'lazy'=>Arr::get($item->getAttribute('hassubordinates'),0) == 'TRUE',
'tooltip'=>$item->getDn(),
];
});
}
public function schema_view(Request $request)
{
$server = new Server;
switch($request->type) {
case 'objectclasses':
return view('fragment.schema.objectclasses')
->with('objectclasses',$server->schema('objectclasses')->sortBy(function($item) { return strtolower($item->name); }));
case 'attributetypes':
return view('fragment.schema.attributetypes')
->with('server',$server)
->with('attributetypes',$server->schema('attributetypes')->sortBy(function($item) { return strtolower($item->name); }));
case 'ldapsyntaxes':
return view('fragment.schema.ldapsyntaxes')
->with('ldapsyntaxes',$server->schema('ldapsyntaxes')->sortBy(function($item) { return strtolower($item->description); }));
case 'matchingrules':
return view('fragment.schema.matchingrules')
->with('matchingrules',$server->schema('matchingrules')->sortBy(function($item) { return strtolower($item->name); }));
default:
abort(404);
}
}
}

View File

@ -1,104 +0,0 @@
<?php
namespace App\Http\Controllers\Auth;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cookie;
use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
class LoginController extends Controller
{
/*
|--------------------------------------------------------------------------
| Login Controller
|--------------------------------------------------------------------------
|
| This controller handles authenticating users for the application and
| redirecting them to your home screen. The controller uses a trait
| to conveniently provide its functionality to your applications.
|
*/
use AuthenticatesUsers;
/**
* Where to redirect users after login.
*
* @var string
*/
protected $redirectTo = RouteServiceProvider::HOME;
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('guest')->except('logout');
}
protected function credentials(Request $request): array
{
return [
login_attr_name() => $request->get(login_attr_name()),
'password' => $request->get('password'),
];
}
/**
* We need to delete our encrypted username/password cookies
*
* @note The rest of this function is the same as a normal laravel logout as in AuthenticatesUsers::class
* @param Request $request
* @return \Illuminate\Contracts\Foundation\Application|JsonResponse|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector|mixed
*/
public function logout(Request $request)
{
// Delete our LDAP authentication cookies
Cookie::queue(Cookie::forget('username_encrypt'));
Cookie::queue(Cookie::forget('password_encrypt'));
$this->guard()->logout();
$request->session()->invalidate();
$request->session()->regenerateToken();
if ($response = $this->loggedOut($request)) {
return $response;
}
return $request->wantsJson()
? new JsonResponse([], 204)
: redirect('/');
}
/**
*
* Show our themed login page
*/
public function showLoginForm()
{
$login_note = '';
if (file_exists('login_note.txt'))
$login_note = file_get_contents('login_note.txt');
return view('architect::auth.login')->with('login_note',$login_note);
}
/**
* Get the login username to be used by the controller.
*
* @return string
*/
public function username()
{
return login_attr_name();
}
}

View File

@ -1,13 +0,0 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller as BaseController;
class Controller extends BaseController
{
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
}

View File

@ -1,309 +0,0 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Arr;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Crypt;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Redirect;
use LdapRecord\Exceptions\InsufficientAccessException;
use LdapRecord\LdapRecordException;
use LdapRecord\Query\ObjectNotFoundException;
use App\Classes\LDAP\{Attribute,Server};
use App\Classes\LDAP\Import\LDIF as LDIFImport;
use App\Classes\LDAP\Export\LDIF as LDIFExport;
use App\Exceptions\Import\{GeneralException,VersionException};
use App\Exceptions\InvalidUsage;
use App\Http\Requests\{EntryRequest,ImportRequest};
use App\Ldap\Entry;
use App\View\Components\AttributeType;
use Nette\NotImplementedException;
class HomeController extends Controller
{
private function bases()
{
$base = Server::baseDNs() ?: collect();
return $base->transform(function($item) {
return [
'title'=>$item->getRdn(),
'item'=>$item->getDNSecure(),
'lazy'=>TRUE,
'icon'=>'fa-fw fas fa-sitemap',
'tooltip'=>$item->getDn(),
];
});
}
/**
* Debug Page
*
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View
*/
public function debug()
{
return view('debug');
}
/**
* Render a specific DN
*
* @param Request $request
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View
*/
public function dn_frame(Request $request)
{
$dn = Crypt::decryptString($request->post('key'));
$page_actions = collect(['edit'=>TRUE,'copy'=>TRUE]);
return view('frames.dn')
->with('o',config('server')->fetch($dn))
->with('dn',$dn)
->with('page_actions',$page_actions);
}
public function entry_export(Request $request,string $id)
{
$dn = Crypt::decryptString($id);
$result = (new Entry)
->query()
//->cache(Carbon::now()->addSeconds(Config::get('ldap.cache.time')))
//->select(['*'])
->setDn($dn)
->recursive()
->get();
return view('fragment.export')
->with('result',new LDIFExport($result));
}
public function entry_newattr(string $id)
{
$x = new AttributeType(new Attribute($id,[]),TRUE);
return $x->render();
}
/**
* Show a confirmation to update a DN
*
* @param EntryRequest $request
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View|\Illuminate\Foundation\Application|\Illuminate\Http\RedirectResponse
* @throws ObjectNotFoundException
*/
public function entry_pending_update(EntryRequest $request)
{
$dn = Crypt::decryptString($request->dn);
$o = config('server')->fetch($dn);
foreach ($request->except(['_token','dn']) as $key => $value)
$o->{$key} = array_filter($value);
if (! $o->getDirty())
return back()
->withInput()
->with('note',__('No attributes changed'));
return view('update')
->with('bases',$this->bases())
->with('dn',$dn)
->with('o',$o);
}
/**
* Update a DN entry
*
* @param EntryRequest $request
* @return \Illuminate\Http\RedirectResponse
* @throws ObjectNotFoundException
*/
public function entry_update(EntryRequest $request)
{
$dn = Crypt::decryptString($request->dn);
$o = config('server')->fetch($dn);
foreach ($request->except(['_token','dn']) as $key => $value)
$o->{$key} = array_filter($value);
if (! $dirty=$o->getDirty())
return back()
->withInput()
->with('note',__('No attributes changed'));
try {
$o->update($request->except(['_token','dn']));
} catch (InsufficientAccessException $e) {
$request->flash();
switch ($x=$e->getDetailedError()->getErrorCode()) {
case 50:
return Redirect::to('/')
->withInput()
->withErrors(sprintf('%s: %s (%s)',__('LDAP Server Error Code'),$x,__($e->getDetailedError()->getErrorMessage())));
default:
abort(599,$e->getDetailedError()->getErrorMessage());
}
} catch (LdapRecordException $e) {
$request->flash();
switch ($x=$e->getDetailedError()->getErrorCode()) {
case 8:
return Redirect::to('/')
->withInput()
->withErrors(sprintf('%s: %s (%s)',__('LDAP Server Error Code'),$x,__($e->getDetailedError()->getErrorMessage())));
default:
abort(599,$e->getDetailedError()->getErrorMessage());
}
}
return Redirect::to('/')
->withInput()
->with('success',__('Entry updated'))
->with('updated',$dirty);
}
/**
* Application home page
*/
public function home()
{
if (old('dn'))
return view('frame')
->with('subframe','dn')
->with('bases',$this->bases())
->with('o',config('server')->fetch($dn=Crypt::decryptString(old('dn'))))
->with('dn',$dn);
elseif (old('frame'))
return view('frame')
->with('subframe',old('frame'))
->with('bases',$this->bases());
else
return view('home')
->with('bases',$this->bases())
->with('server',config('ldap.connections.default.name'));
}
/**
* Process the incoming LDIF file or LDIF text
*
* @param ImportRequest $request
* @param string $type
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View|\Illuminate\Foundation\Application
* @throws GeneralException
* @throws VersionException
*/
public function import(ImportRequest $request,string $type)
{
switch ($type) {
case 'ldif':
$import = new LDIFImport($x=($request->text ?: $request->file->get()));
break;
default:
abort(404,'Unknown import type: '.$type);
}
try {
$result = $import->process();
} catch (NotImplementedException $e) {
abort(555,$e->getMessage());
} catch (\Exception $e) {
abort(598,$e->getMessage());
}
return view('frame')
->with('subframe','import_result')
->with('bases',$this->bases())
->with('result',$result)
->with('ldif',htmlspecialchars($x));
}
public function import_frame()
{
return view('frames.import');
}
/**
* LDAP Server INFO
*
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View
*/
public function info()
{
return view('frames.info')
->with('s',config('server'));
}
/**
* Show the Schema Viewer
*
* @note Our route will validate that types are valid.
* @param Request $request
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View
* @throws InvalidUsage
*/
public function schema_frame(Request $request)
{
$s = config('server');
// If an invalid key, we'll 404
if ($request->type && $request->key && ($s->schema($request->type)->has($request->key) === FALSE))
abort(404);
return view('frames.schema')
->with('type',$request->type)
->with('key',$request->key);
}
/**
* Sort the attributes
*
* @param Collection $attrs
* @return Collection
*/
private function sortAttrs(Collection $attrs): Collection
{
return $attrs->sortKeys();
}
/**
* Return the image for the logged in user or anonymous
*
* @param Request $request
* @return mixed
*/
public function user_image(Request $request)
{
$image = NULL;
$content = NULL;
if (Auth::check()) {
$image = Arr::get(Auth::user()->getAttribute('jpegphoto'),0);
$content = 'image/jpeg';
}
if (! $image) {
$image = File::get('../resources/images/user-secret-solid.svg');
$content = 'image/svg+xml';
}
return response($image)
->header('Content-Type',$content);
}
}

View File

@ -1,82 +0,0 @@
<?php
namespace App\Http;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
use App\Http\Middleware\{ApplicationSession,CheckUpdate,SwapinAuthUser};
class Kernel extends HttpKernel
{
/**
* The application's global HTTP middleware stack.
*
* These middleware are run during every request to your application.
*
* @var array
*/
protected $middleware = [
// \App\Http\Middleware\TrustHosts::class,
\App\Http\Middleware\TrustProxies::class,
\Illuminate\Http\Middleware\HandleCors::class,
\App\Http\Middleware\CheckForMaintenanceMode::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
];
/**
* The application's route middleware groups.
*
* @var array
*/
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
ApplicationSession::class,
SwapinAuthUser::class,
\Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\Laravel\Passport\Http\Middleware\CreateFreshApiToken::class,
CheckUpdate::class,
],
'api' => [
'throttle:60,1',
\App\Http\Middleware\EncryptCookies::class,
SwapinAuthUser::class,
ApplicationSession::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
];
/**
* The application's route middleware.
*
* These middleware may be assigned to groups or used individually.
*
* @var array
*/
protected $middlewareAliases = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
'localize' => \Mcamara\LaravelLocalization\Middleware\LaravelLocalizationRoutes::class,
'localizationRedirect' => \Mcamara\LaravelLocalization\Middleware\LaravelLocalizationRedirectFilter::class,
'localeSessionRedirect' => \Mcamara\LaravelLocalization\Middleware\LocaleSessionRedirect::class,
'localeCookieRedirect' => \Mcamara\LaravelLocalization\Middleware\LocaleCookieRedirect::class,
'localeViewPath' => \Mcamara\LaravelLocalization\Middleware\LaravelLocalizationViewPath::class
];
}

View File

@ -1,29 +0,0 @@
<?php
namespace App\Http\Middleware;
use App\Classes\LDAP\Server;
use App\Ldap\User;
use Closure;
/**
* This sets up our application session with any required values, ultimately for cache optimisation reasons
*/
class ApplicationSession
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request,Closure $next)
{
\Config::set('server',new Server);
view()->share('user', auth()->user() ?: new User);
return $next($request);
}
}

View File

@ -1,21 +0,0 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Auth\Middleware\Authenticate as Middleware;
class Authenticate extends Middleware
{
/**
* Get the path the user should be redirected to when they are not authenticated.
*
* @param \Illuminate\Http\Request $request
* @return string|null
*/
protected function redirectTo($request)
{
if (! $request->expectsJson()) {
return route('login');
}
}
}

View File

@ -1,17 +0,0 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode as Middleware;
class CheckForMaintenanceMode extends Middleware
{
/**
* The URIs that should be reachable while maintenance mode is enabled.
*
* @var array
*/
protected $except = [
//
];
}

View File

@ -1,61 +0,0 @@
<?php
namespace App\Http\Middleware;
use Closure;
use GuzzleHttp\Client;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;
class CheckUpdate
{
private const UPDATE_SERVER = 'https://version.phpldapadmin.org';
private const UPDATE_TIME = 60*60*6;
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
\Config::set('update_available',Cache::get('upstream_version'));
return $next($request);
}
/**
* Handle tasks after the response has been sent to the browser.
*
* @return void
*/
public function terminate()
{
Cache::remember('upstream_version',self::UPDATE_TIME,function() {
// CURL call to URL to see if there is a new version
Log::debug(sprintf('CU_:Checking for updates for [%s]',config('app.version')));
$client = new Client;
try {
$response = $client->request('POST',sprintf('%s/%s',self::UPDATE_SERVER,strtolower(config('app.version'))));
if ($response->getStatusCode() === 200) {
$result = json_decode($response->getBody());
Log::debug(sprintf('CU_:- Update server returned...'),['update'=>$result]);
return $result;
}
} catch (\Exception $e) {
Log::debug(sprintf('CU_:- Exception connecting to update server'),['e'=>get_class($e)]);
}
return NULL;
});
}
}

View File

@ -1,17 +0,0 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Cookie\Middleware\EncryptCookies as Middleware;
class EncryptCookies extends Middleware
{
/**
* The names of the cookies that should not be encrypted.
*
* @var array
*/
protected $except = [
//
];
}

View File

@ -1,27 +0,0 @@
<?php
namespace App\Http\Middleware;
use App\Providers\RouteServiceProvider;
use Closure;
use Illuminate\Support\Facades\Auth;
class RedirectIfAuthenticated
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param string|null $guard
* @return mixed
*/
public function handle($request, Closure $next, $guard = null)
{
if (Auth::guard($guard)->check()) {
return redirect(RouteServiceProvider::HOME);
}
return $next($request);
}
}

View File

@ -1,50 +0,0 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Cookie;
// use Illuminate\Support\Facades\Crypt;
use Illuminate\Support\Facades\Log;
// use Illuminate\Support\Facades\Session;
use LdapRecord\Container;
use App\Ldap\Connection;
class SwapinAuthUser
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse) $next
* @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
*/
public function handle(Request $request, Closure $next)
{
$key = config('ldap.default');
/*
// Rebuild our connection with the authenticated user.
if (Session::has('username_encrypt') && Session::has('password_encrypt')) {
Config::set('ldap.connections.'.$key.'.username',Crypt::decryptString(Session::get('username_encrypt')));
Config::set('ldap.connections.'.$key.'.password',Crypt::decryptString(Session::get('password_encrypt')));
} else
*/
if (Cookie::has('username_encrypt') && Cookie::has('password_encrypt')) {
Config::set('ldap.connections.'.$key.'.username',Cookie::get('username_encrypt'));
Config::set('ldap.connections.'.$key.'.password',Cookie::get('password_encrypt'));
Log::debug('Swapping out configured LDAP credentials with the user\'s cookie.');
}
// We need to override our Connection object so that we can store and retrieve the logged in user and swap out the credentials to use them.
Container::getInstance()->addConnection(new Connection(config('ldap.connections.'.$key)),$key);
return $next($request);
}
}

View File

@ -1,18 +0,0 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\TrimStrings as Middleware;
class TrimStrings extends Middleware
{
/**
* The names of the attributes that should not be trimmed.
*
* @var array
*/
protected $except = [
'password',
'password_confirmation',
];
}

View File

@ -1,20 +0,0 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Http\Middleware\TrustHosts as Middleware;
class TrustHosts extends Middleware
{
/**
* Get the host patterns that should be trusted.
*
* @return array
*/
public function hosts()
{
return [
$this->allSubdomainsOfApplicationUrl(),
];
}
}

View File

@ -1,28 +0,0 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Http\Middleware\TrustProxies as Middleware;
use Illuminate\Http\Request;
class TrustProxies extends Middleware
{
/**
* The trusted proxies for this application.
*
* @var array<int, string>|string|null
*/
protected $proxies;
/**
* The headers that should be used to detect proxies.
*
* @var int
*/
protected $headers =
Request::HEADER_X_FORWARDED_FOR |
Request::HEADER_X_FORWARDED_HOST |
Request::HEADER_X_FORWARDED_PORT |
Request::HEADER_X_FORWARDED_PROTO |
Request::HEADER_X_FORWARDED_AWS_ELB;
}

View File

@ -1,17 +0,0 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;
class VerifyCsrfToken extends Middleware
{
/**
* The URIs that should be excluded from CSRF verification.
*
* @var array
*/
protected $except = [
//
];
}

View File

@ -1,34 +0,0 @@
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class EntryRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return TRUE;
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, mixed>
*/
public function rules()
{
return config('server')
->schema('attributetypes')
->intersectByKeys($this->request)
->transform(function($item) { return $item->validation; })
->filter()
->flatMap(function($item) { return $item; })
->toArray();
}
}

View File

@ -1,22 +0,0 @@
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class ImportRequest extends FormRequest
{
public function authorize()
{
return TRUE;
}
public function rules()
{
return [
'frame' => 'required|string|in:import',
'file' => 'nullable|extensions:ldif|required_without:text',
'text'=> 'nullable|prohibits:file|string|min:16',
];
}
}

View File

@ -1,20 +0,0 @@
<?php
namespace App\Ldap;
use LdapRecord\Connection as ConnectionBase;
use LdapRecord\LdapInterface;
class Connection extends ConnectionBase
{
public function __construct($config = [], LdapInterface $ldap = null)
{
parent::__construct($config,$ldap);
// We need to override this so that we use our own Guard, that stores the users credentials in the session
$this->authGuardResolver = function () {
return new Guard($this->ldap, $this->configuration);
};
}
}

View File

@ -1,423 +0,0 @@
<?php
namespace App\Ldap;
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;
use App\Classes\LDAP\Export\LDIF;
use App\Exceptions\Import\AttributeException;
class Entry extends Model
{
private Collection $objects;
private bool $noObjectAttributes = FALSE;
/* OVERRIDES */
public function __construct(array $attributes = [])
{
$this->objects = collect();
parent::__construct($attributes);
}
public function discardChanges(): static
{
parent::discardChanges();
// If we are discharging changes, we need to reset our $objects;
$this->objects = $this->getAttributesAsObjects($this->attributes);
return $this;
}
/**
* This function overrides getAttributes to use our collection of Attribute objects instead of the models attributes.
*
* @return array
* @note $this->attributes may not be updated with changes
*/
public function getAttributes(): array
{
return $this->objects->map(function($item) { return $item->values->toArray(); })->toArray();
}
/**
* Determine if the new and old values for a given key are equivalent.
*/
protected function originalIsEquivalent(string $key): bool
{
$key = $this->normalizeAttributeKey($key);
if ((! array_key_exists($key, $this->original)) && (! $this->objects->has($key))) {
return TRUE;
}
$current = $this->attributes[$key];
$original = $this->objects->get($key)->values;
if ($current === $original) {
return true;
}
return ! $this->getObject($key)->isDirty();
}
public static function query(bool $noattrs=false): Builder
{
$o = new static;
if ($noattrs)
$o->noObjectAttributes();
return $o->newQuery();
}
/**
* As attribute values are updated, or new ones created, we need to mirror that
* into our $objects
*
* @param string $key
* @param mixed $value
* @return $this
*/
public function setAttribute(string $key, mixed $value): static
{
parent::setAttribute($key,$value);
$key = $this->normalizeAttributeKey($key);
if ((! $this->objects->get($key)) && $value) {
$o = new Attribute($key,[]);
$o->value = $value;
$this->objects->put($key,$o);
} elseif ($this->objects->get($key)) {
$this->objects->get($key)->value = $this->attributes[$key];
}
return $this;
}
/**
* We'll shadow $this->attributes to $this->objects - a collection of Attribute objects
*
* Using the objects, it'll make it easier to work with attribute values
*
* @param array $attributes
* @return $this
*/
public function setRawAttributes(array $attributes = []): static
{
parent::setRawAttributes($attributes);
// We only set our objects on DN entries (otherwise we might get into a recursion loop if this is the schema DN)
if ($this->dn && (! in_array($this->dn,Arr::get($this->attributes,'subschemasubentry',[])))) {
$this->objects = $this->getAttributesAsObjects($this->attributes);
} else {
$this->objects = collect();
}
return $this;
}
/* ATTRIBUTES */
/**
* Return a key to use for sorting
*
* @todo This should be the DN in reverse order
* @return string
*/
public function getSortKeyAttribute(): string
{
return $this->getDn();
}
/* METHODS */
public function addAttribute(string $key,mixed $value): void
{
$key = $this->normalizeAttributeKey($key);
if (config('server')->schema('attributetypes')->has($key) === FALSE)
throw new AttributeException('Schema doesnt have attribute [%s]',$key);
if ($x=$this->objects->get($key)) {
$x->addValue($value);
} else {
$this->objects->put($key,Attribute\Factory::create($key,Arr::wrap($value)));
}
}
/**
* Convert all our attribute values into an array of Objects
*
* @param array $attributes
* @return Collection
*/
protected function getAttributesAsObjects(array $attributes): Collection
{
$result = collect();
foreach ($attributes as $attribute => $value) {
// If the attribute name has language tags
$matches = [];
if (preg_match('/^([a-zA-Z]+)(;([a-zA-Z-;]+))+/',$attribute,$matches)) {
$attribute = $matches[1];
// If the attribute doesnt exist we'll create it
$o = Arr::get($result,$attribute,Factory::create($attribute,[]));
$o->setLangTag($matches[3],$value);
} else {
$o = Factory::create($attribute,$value);
}
if (! $result->has($attribute)) {
// Set the rdn flag
if (preg_match('/^'.$attribute.'=/i',$this->dn))
$o->setRDN();
// Set required flag
$o->required_by(collect($this->getAttribute('objectclass')));
// Store our original value to know if this attribute has changed
if ($x=Arr::get($this->original,$attribute))
$o->oldValues($x);
$result->put($attribute,$o);
}
}
$sort = collect(config('ldap.attr_display_order',[]))->transform(function($item) { return strtolower($item); });
// Order the attributes
$result = $result->sortBy([function(Attribute $a,Attribute $b) use ($sort): int {
if ($a === $b)
return 0;
// Check if $a/$b are in the configuration to be sorted first, if so get it's key
$a_key = $sort->search($a->name_lc);
$b_key = $sort->search($b->name_lc);
// If the keys were not in the sort list, set the key to be the count of elements (ie: so it is last to be sorted)
if ($a_key === FALSE)
$a_key = $sort->count()+1;
if ($b_key === FALSE)
$b_key = $sort->count()+1;
// Case where neither $a, nor $b are in ldap.attr_display_order, $a_key = $b_key = one greater than num elements.
// So we sort them alphabetically
if ($a_key === $b_key)
return strcasecmp($a->name,$b->name);
// Case where at least one attribute or its friendly name is in $attrs_display_order
// return -1 if $a before $b in $attrs_display_order
return ($a_key < $b_key) ? -1 : 1;
} ]);
return $result;
}
/**
* Return a list of available attributes - as per the objectClass entry of the record
*
* @return Collection
*/
public function getAvailableAttributes(): Collection
{
$result = collect();
foreach ($this->objectclass as $oc)
$result = $result->merge(config('server')->schema('objectclasses',$oc)->attributes);
return $result;
}
/**
* Return a secure version of the DN
* @return string
*/
public function getDNSecure(): string
{
return Crypt::encryptString($this->getDn());
}
/**
* Return a list of LDAP internal attributes
*
* @return Collection
*/
public function getInternalAttributes(): Collection
{
return $this->objects->filter(function($item) {
return $item->is_internal;
});
}
/**
* Get an attribute as an object
*
* @param string $key
* @return Attribute|null
*/
public function getObject(string $key): Attribute|null
{
return $this->objects->get($this->normalizeAttributeKey($key));
}
public function getObjects(): Collection
{
// In case we havent built our objects yet (because they werent available while determining the schema DN)
if ((! $this->objects->count()) && $this->attributes)
$this->objects = $this->getAttributesAsObjects($this->attributes);
return $this->objects;
}
/**
* Return a list of attributes without any values
*
* @return Collection
*/
public function getMissingAttributes(): Collection
{
return $this->getAvailableAttributes()->diff($this->getVisibleAttributes());
}
/**
* Return this list of user attributes
*
* @return Collection
*/
public function getVisibleAttributes(): Collection
{
return $this->objects->filter(function($item) {
return ! $item->is_internal;
});
}
public function hasAttribute(int|string $key): bool
{
return $this->objects->has($key);
}
/**
* Export this record
*
* @param string $method
* @param string $scope
* @return string
* @throws \Exception
*/
public function export(string $method,string $scope): string
{
// @todo To implement
switch ($scope) {
case 'base':
case 'one':
case 'sub':
break;
default:
throw new \Exception('Export scope unknown:'.$scope);
}
switch ($method) {
case 'ldif':
return new LDIF(collect($this));
default:
throw new \Exception('Export method not implemented:'.$method);
}
}
/**
* Return an icon for a DN based on objectClass
*
* @return string
*/
public function icon(): string
{
$objectclasses = array_map('strtolower',$this->objectclass);
// Return icon based upon objectClass value
if (in_array('person',$objectclasses) ||
in_array('organizationalperson',$objectclasses) ||
in_array('inetorgperson',$objectclasses) ||
in_array('account',$objectclasses) ||
in_array('posixaccount',$objectclasses))
return 'fas fa-user';
elseif (in_array('organization',$objectclasses))
return 'fas fa-university';
elseif (in_array('organizationalunit',$objectclasses))
return 'fas fa-object-group';
elseif (in_array('posixgroup',$objectclasses) ||
in_array('groupofnames',$objectclasses) ||
in_array('groupofuniquenames',$objectclasses) ||
in_array('group',$objectclasses))
return 'fas fa-users';
elseif (in_array('dcobject',$objectclasses) ||
in_array('domainrelatedobject',$objectclasses) ||
in_array('domain',$objectclasses) ||
in_array('builtindomain',$objectclasses))
return 'fas fa-network-wired';
elseif (in_array('alias',$objectclasses))
return 'fas fa-theater-masks';
elseif (in_array('country',$objectclasses))
return sprintf('flag %s',strtolower(Arr::get($this->c,0)));
elseif (in_array('device',$objectclasses))
return 'fas fa-mobile-alt';
elseif (in_array('document',$objectclasses))
return 'fas fa-file-alt';
elseif (in_array('iphost',$objectclasses))
return 'fas fa-wifi';
elseif (in_array('room',$objectclasses))
return 'fas fa-door-open';
elseif (in_array('server',$objectclasses))
return 'fas fa-server';
elseif (in_array('openldaprootdse',$objectclasses))
return 'fas fa-info';
// Default
return 'fa-fw fas fa-cog';
}
/**
* Dont convert our $this->attributes to $this->objects when creating a new Entry::class
*
* @return $this
*/
public function noObjectAttributes(): static
{
$this->noObjectAttributes = TRUE;
return $this;
}
}

View File

@ -1,29 +0,0 @@
<?php
namespace App\Ldap;
use Illuminate\Support\Facades\Cookie;
// use Illuminate\Support\Facades\Crypt;
use LdapRecord\Auth\Guard as GuardBase;
class Guard extends GuardBase
{
public function attempt(string $username, string $password, bool $stayBound = false): bool
{
if ($result = parent::attempt($username,$password,$stayBound)) {
/*
* We can either use our session or cookies to store this. If using session, then Http/Kernel needs to be
* updated to start a session for API calls.
// We need to store our password so that we can swap in the user in during SwapinAuthUser::class middleware
request()->session()->put('username_encrypt',Crypt::encryptString($username));
request()->session()->put('password_encrypt',Crypt::encryptString($password));
*/
// For our API calls, we store the cookie - which our cookies are already encrypted
Cookie::queue('username_encrypt',$username);
Cookie::queue('password_encrypt',$password);
}
return $result;
}
}

View File

@ -1,79 +0,0 @@
<?php
namespace App\Ldap;
use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Support\Str;
use LdapRecord\Laravel\Events\Auth\DiscoveredWithCredentials;
use LdapRecord\Laravel\LdapUserRepository as LdapUserRepositoryBase;
use LdapRecord\Models\Model;
use App\Classes\LDAP\Server;
class LdapUserRepository extends LdapUserRepositoryBase
{
/**
* Retrieve a user by the given credentials.
*
* @param array $credentials
*
* @return Model|null
* @throws \LdapRecord\Query\ObjectNotFoundException
*/
public function findByCredentials(array $credentials = []): ?Model
{
if (empty($credentials)) {
return NULL;
}
// For DN based logins
if (! empty($credentials['dn']))
return $this->query()->find($credentials['dn']);
// Look for a user using all our baseDNs
foreach (Server::baseDNs() as $base) {
$query = $this->query()->setBaseDn($base);
foreach ($credentials as $key => $value) {
if (Str::contains($key, $this->bypassCredentialKeys)) {
continue;
}
if (is_array($value) || $value instanceof Arrayable) {
$query->whereIn($key, $value);
} else {
$query->where($key, $value);
}
}
if (! is_null($user = $query->first())) {
event(new DiscoveredWithCredentials($user));
return $user;
}
}
return NULL;
}
/**
* Get a user by their object GUID.
*
* @param string $guid
*
* @return Model|null
* @throws \LdapRecord\Query\ObjectNotFoundException
*/
public function findByGuid($guid): ?Model
{
// Look for a user using all our baseDNs
foreach (Server::baseDNs() as $base) {
$user = $this->query()->setBaseDn($base)->findByGuid($guid);
if ($user)
return $user;
}
return NULL;
}
}

View File

@ -1,27 +0,0 @@
<?php
namespace App\Ldap\Rules;
use Illuminate\Database\Eloquent\Model as Eloquent;
use LdapRecord\Laravel\Auth\Rule;
use LdapRecord\Models\Model as LdapRecord;
/**
* User must have this objectClass to login
*
* This is overridden by LDAP_LOGIN_OBJECTCLASS
* @see User::$objectClasses
*/
class LoginObjectclassRule implements Rule
{
public function passes(LdapRecord $user, Eloquent $model = null): bool
{
if ($x=config('ldap.login.objectclass')) {
return count(array_intersect($user->objectclass,$x));
// Otherwise allow the user to login
} else {
return TRUE;
}
}
}

View File

@ -1,29 +0,0 @@
<?php
namespace App\Ldap;
use Laravel\Passport\HasApiTokens;
use LdapRecord\Models\OpenLDAP\User as Model;
use App\Ldap\Rules\LoginObjectclassRule;
class User extends Model
{
use HasApiTokens;
/**
* The object classes of the LDAP model.
*
* @note We set this to an empty array so that any objectclass can login
* @see LoginObjectclassRule::class
*/
public static array $objectClasses = [
];
/* METHODS */
public function getDn(): string
{
return $this->exists ? parent::getDn() : 'Anonymous';
}
}

View File

@ -1,44 +0,0 @@
<?php
namespace App\Providers;
use Illuminate\Support\Collection;
use Illuminate\Support\ServiceProvider;
use LdapRecord\Configuration\DomainConfiguration;
use LdapRecord\Laravel\LdapRecord;
use App\Ldap\LdapUserRepository;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* @return void
*/
public function register()
{
// Add a new option available to be set in the configuration:
DomainConfiguration::extend('name', $default = null);
// Use our LdapUserRepository to support multiple baseDN querying
LdapRecord::locateUsersUsing(LdapUserRepository::class);
}
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
$this->loadViewsFrom(__DIR__.'/../../resources/themes/architect/views/','architect');
// Enable pluck on collections to work on private values
Collection::macro('ppluck', function ($attr) {
return $this->map(function (object $item) use ($attr) {
return $item->{$attr};
})->values();
});
}
}

View File

@ -1,27 +0,0 @@
<?php
namespace App\Providers;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
class AuthServiceProvider extends ServiceProvider
{
/**
* The model to policy mappings for the application.
*
* @var array<class-string, class-string>
*/
protected $policies = [
// 'App\Models\Model' => 'App\Policies\ModelPolicy',
];
/**
* Register any authentication / authorization services.
*
* @return void
*/
public function boot()
{
//
}
}

View File

@ -1,21 +0,0 @@
<?php
namespace App\Providers;
use Illuminate\Support\Facades\Broadcast;
use Illuminate\Support\ServiceProvider;
class BroadcastServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
Broadcast::routes();
require base_path('routes/channels.php');
}
}

View File

@ -1,30 +0,0 @@
<?php
namespace App\Providers;
use Illuminate\Auth\Events\Registered;
use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Event;
class EventServiceProvider extends ServiceProvider
{
/**
* The event listener mappings for the application.
*
* @var array
*/
protected $listen = [];
/**
* Register any events for your application.
*
* @return void
*/
public function boot()
{
parent::boot();
//
}
}

View File

@ -1,52 +0,0 @@
<?php
namespace App\Providers;
use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\Facades\Route;
class RouteServiceProvider extends ServiceProvider
{
/**
* The path to the "home" route for your application.
*
* Typically, users are redirected here after authentication.
*
* @var string
*/
public const HOME = '/';
/**
* Define your route model bindings, pattern filters, and other route configuration.
*
* @return void
*/
public function boot()
{
$this->configureRateLimiting();
$this->routes(function () {
Route::middleware('api')
->prefix('api')
->group(base_path('routes/api.php'));
Route::middleware('web')
->group(base_path('routes/web.php'));
});
}
/**
* Configure the rate limiters for the application.
*
* @return void
*/
protected function configureRateLimiting()
{
RateLimiter::for('api', function (Request $request) {
return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip());
});
}
}

View File

@ -1,23 +0,0 @@
<?php
/**
* Determine if a value has changed by comparing its MD5 value
*/
namespace App\Traits;
use Illuminate\Support\Arr;
trait MD5Updates
{
public function isDirty(): bool
{
if (! parent::isDirty())
return TRUE;
foreach ($this->values->diff($this->oldValues) as $key => $value)
if (md5(Arr::get($this->oldValues,$key)) !== $value)
return TRUE;
return FALSE;
}
}

View File

@ -1,38 +0,0 @@
<?php
namespace App\View\Components;
use Illuminate\View\Component;
use App\Classes\LDAP\Attribute as LDAPAttribute;
class Attribute extends Component
{
public LDAPAttribute $o;
public bool $edit;
public bool $new;
public bool $old;
/**
* Create a new component instance.
*
* @return void
*/
public function __construct(LDAPAttribute $o,bool $edit,bool $old=FALSE,bool $new=FALSE)
{
$this->o = $o;
$this->edit = $edit;
$this->old = $old;
$this->new = $new;
}
/**
* Get the view / contents that represent the component.
*
* @return \Illuminate\Contracts\View\View|\Closure|string
*/
public function render()
{
return $this->o->render($this->edit,$this->old,$this->new);
}
}

View File

@ -1,34 +0,0 @@
<?php
namespace App\View\Components;
use Closure;
use Illuminate\Contracts\View\View;
use Illuminate\View\Component;
use App\Classes\LDAP\Attribute as LDAPAttribute;
class AttributeType extends Component
{
public LDAPAttribute $o;
public bool $new;
/**
* Create a new component instance.
*/
public function __construct(LDAPAttribute $o,bool $new=FALSE)
{
$this->o = $o;
$this->new = $new;
}
/**
* Get the view / contents that represent the component.
*/
public function render(): View|Closure|string
{
return view('components.attribute-type')
->with('o',$this->o)
->with('new',$this->new);
}
}

View File

@ -1,13 +0,0 @@
<?php
use Illuminate\Support\Arr;
function login_attr_description(): string
{
return Arr::get(config('ldap.login.attr'),login_attr_name());
}
function login_attr_name(): string
{
return key(config('ldap.login.attr'));
}

53
artisan
View File

@ -1,53 +0,0 @@
#!/usr/bin/env php
<?php
define('LARAVEL_START', microtime(true));
/*
|--------------------------------------------------------------------------
| Register The Auto Loader
|--------------------------------------------------------------------------
|
| Composer provides a convenient, automatically generated class loader
| for our application. We just need to utilize it! We'll require it
| into the script here so that we do not have to worry about the
| loading of any of our classes manually. It's great to relax.
|
*/
require __DIR__.'/vendor/autoload.php';
$app = require_once __DIR__.'/bootstrap/app.php';
/*
|--------------------------------------------------------------------------
| Run The Artisan Application
|--------------------------------------------------------------------------
|
| When we run the console application, the current CLI command will be
| executed in this console and the response sent back to a terminal
| or another output device for the developers. Here goes nothing!
|
*/
$kernel = $app->make(Illuminate\Contracts\Console\Kernel::class);
$status = $kernel->handle(
$input = new Symfony\Component\Console\Input\ArgvInput,
new Symfony\Component\Console\Output\ConsoleOutput
);
/*
|--------------------------------------------------------------------------
| Shutdown The Application
|--------------------------------------------------------------------------
|
| Once Artisan has finished running, we will fire off the shutdown events
| so that any final work may be done by the application before we shut
| down the process. This is the last thing to happen to the request.
|
*/
$kernel->terminate($input, $status);
exit($status);

View File

@ -1,55 +0,0 @@
<?php
/*
|--------------------------------------------------------------------------
| Create The Application
|--------------------------------------------------------------------------
|
| The first thing we will do is create a new Laravel application instance
| which serves as the "glue" for all the components of Laravel, and is
| the IoC container for the system binding all of the various parts.
|
*/
$app = new Illuminate\Foundation\Application(
$_ENV['APP_BASE_PATH'] ?? dirname(__DIR__)
);
/*
|--------------------------------------------------------------------------
| Bind Important Interfaces
|--------------------------------------------------------------------------
|
| Next, we need to bind some important interfaces into the container so
| we will be able to resolve them when needed. The kernels serve the
| incoming requests to this application from both the web and CLI.
|
*/
$app->singleton(
Illuminate\Contracts\Http\Kernel::class,
App\Http\Kernel::class
);
$app->singleton(
Illuminate\Contracts\Console\Kernel::class,
App\Console\Kernel::class
);
$app->singleton(
Illuminate\Contracts\Debug\ExceptionHandler::class,
App\Exceptions\Handler::class
);
/*
|--------------------------------------------------------------------------
| Return The Application
|--------------------------------------------------------------------------
|
| This script returns the application instance. The instance is given to
| the calling script so we can separate the building of the instances
| from the actual running of the application and sending responses.
|
*/
return $app;

View File

@ -1,2 +0,0 @@
*
!.gitignore

View File

@ -1,65 +0,0 @@
{
"name": "laravel/laravel",
"type": "project",
"description": "The Laravel Framework.",
"keywords": ["framework","laravel"],
"license": "MIT",
"require": {
"ext-fileinfo": "*",
"ext-ldap": "*",
"php": "^8.1|8.2",
"directorytree/ldaprecord-laravel": "^3.0",
"guzzlehttp/guzzle": "^7.2",
"laravel/framework": "^10.0",
"laravel/passport": "^11.0",
"laravel/ui": "^4.0",
"mcamara/laravel-localization": "^1.7"
},
"require-dev": {
"barryvdh/laravel-debugbar": "^3.5",
"fakerphp/faker": "^1.9.1",
"mockery/mockery": "^1.4.4",
"nunomaduro/collision": "^7.10",
"phpunit/phpunit": "^10.0",
"spatie/laravel-ignition": "^2.4"
},
"autoload": {
"files": [
"app/helpers.php"
],
"psr-4": {
"App\\": "app/",
"Database\\Factories\\": "database/factories/",
"Database\\Seeders\\": "database/seeders/"
}
},
"autoload-dev": {
"psr-4": {
"Tests\\": "tests/"
}
},
"scripts": {
"post-autoload-dump": [
"Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
"@php artisan package:discover --ansi"
],
"post-root-package-install": [
"@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
],
"post-create-project-cmd": [
"@php artisan key:generate --ansi"
]
},
"extra": {
"laravel": {
"dont-discover": []
}
},
"config": {
"optimize-autoloader": true,
"preferred-install": "dist",
"sort-packages": true
},
"minimum-stability": "stable",
"prefer-stable": true
}

9231
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -1,203 +0,0 @@
<?php
use Illuminate\Support\Facades\Facade;
return [
/*
|--------------------------------------------------------------------------
| Application Name
|--------------------------------------------------------------------------
|
| This value is the name of your application. This value is used when the
| framework needs to place the application's name in a notification or
| any other location as required by the application or its packages.
|
*/
'name' => 'PLA',
'name_html_long' => '<b>php</b>LDAPadmin',
'version' => (trim(file_get_contents(__DIR__.'/../public/VERSION')) ?? 'UNKNOWN').'-'.(trim(file_get_contents(__DIR__.'/../VERSION')) ?? 'UNKNOWN'),
/*
|--------------------------------------------------------------------------
| Application Environment
|--------------------------------------------------------------------------
|
| This value determines the "environment" your application is currently
| running in. This may determine how you prefer to configure various
| services the application utilizes. Set this in your ".env" file.
|
*/
'env' => env('APP_ENV', 'production'),
/*
|--------------------------------------------------------------------------
| Application Debug Mode
|--------------------------------------------------------------------------
|
| When your application is in debug mode, detailed error messages with
| stack traces will be shown on every error that occurs within your
| application. If disabled, a simple generic error page is shown.
|
*/
'debug' => (bool) env('APP_DEBUG', false),
/*
|--------------------------------------------------------------------------
| Application URL
|--------------------------------------------------------------------------
|
| This URL is used by the console to properly generate URLs when using
| the Artisan command line tool. You should set this to the root of
| your application so that it is used when running Artisan tasks.
|
*/
'url' => env('APP_URL', 'http://localhost'),
'asset_url' => env('ASSET_URL', null),
/*
|--------------------------------------------------------------------------
| Application Timezone
|--------------------------------------------------------------------------
|
| Here you may specify the default timezone for your application, which
| will be used by the PHP date and date-time functions. We have gone
| ahead and set this to a sensible default for you out of the box.
|
*/
'timezone' => 'UTC',
/*
|--------------------------------------------------------------------------
| Application Locale Configuration
|--------------------------------------------------------------------------
|
| The application locale determines the default locale that will be used
| by the translation service provider. You are free to set this value
| to any of the locales which will be supported by the application.
|
*/
'locale' => 'en',
/*
|--------------------------------------------------------------------------
| Application Fallback Locale
|--------------------------------------------------------------------------
|
| The fallback locale determines the locale to use when the current one
| is not available. You may change the value to correspond to any of
| the language folders that are provided through your application.
|
*/
'fallback_locale' => 'en',
/*
|--------------------------------------------------------------------------
| Faker Locale
|--------------------------------------------------------------------------
|
| This locale will be used by the Faker PHP library when generating fake
| data for your database seeds. For example, this will be used to get
| localized telephone numbers, street address information and more.
|
*/
'faker_locale' => 'en_US',
/*
|--------------------------------------------------------------------------
| Encryption Key
|--------------------------------------------------------------------------
|
| This key is used by the Illuminate encrypter service and should be set
| to a random, 32 character string, otherwise these encrypted strings
| will not be safe. Please do this before deploying an application!
|
*/
'key' => env('APP_KEY'),
'cipher' => 'AES-256-CBC',
/*
|--------------------------------------------------------------------------
| Autoloaded Service Providers
|--------------------------------------------------------------------------
|
| The service providers listed here will be automatically loaded on the
| request to your application. Feel free to add your own services to
| this array to grant expanded functionality to your applications.
|
*/
'providers' => [
/*
* Laravel Framework Service Providers...
*/
Illuminate\Auth\AuthServiceProvider::class,
Illuminate\Broadcasting\BroadcastServiceProvider::class,
Illuminate\Bus\BusServiceProvider::class,
Illuminate\Cache\CacheServiceProvider::class,
Illuminate\Foundation\Providers\ConsoleSupportServiceProvider::class,
Illuminate\Cookie\CookieServiceProvider::class,
Illuminate\Database\DatabaseServiceProvider::class,
Illuminate\Encryption\EncryptionServiceProvider::class,
Illuminate\Filesystem\FilesystemServiceProvider::class,
Illuminate\Foundation\Providers\FoundationServiceProvider::class,
Illuminate\Hashing\HashServiceProvider::class,
Illuminate\Mail\MailServiceProvider::class,
Illuminate\Notifications\NotificationServiceProvider::class,
Illuminate\Pagination\PaginationServiceProvider::class,
Illuminate\Pipeline\PipelineServiceProvider::class,
Illuminate\Queue\QueueServiceProvider::class,
Illuminate\Redis\RedisServiceProvider::class,
Illuminate\Auth\Passwords\PasswordResetServiceProvider::class,
Illuminate\Session\SessionServiceProvider::class,
Illuminate\Translation\TranslationServiceProvider::class,
Illuminate\Validation\ValidationServiceProvider::class,
Illuminate\View\ViewServiceProvider::class,
/*
* Package Service Providers...
*/
/*
* Application Service Providers...
*/
App\Providers\AppServiceProvider::class,
App\Providers\AuthServiceProvider::class,
// App\Providers\BroadcastServiceProvider::class,
App\Providers\EventServiceProvider::class,
App\Providers\RouteServiceProvider::class,
/*
* Other Service Providers...
*/
],
/*
|--------------------------------------------------------------------------
| Class Aliases
|--------------------------------------------------------------------------
|
| This array of class aliases will be registered when this application
| is started. However, feel free to register as many as you wish as
| the aliases are "lazy" loaded so they don't hinder performance.
|
*/
'aliases' => Facade::defaultAliases()->merge([
// 'ExampleClass' => App\Example\ExampleClass::class,
])->toArray(),
];

View File

@ -1,125 +0,0 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Authentication Defaults
|--------------------------------------------------------------------------
|
| This option controls the default authentication "guard" and password
| reset options for your application. You may change these defaults
| as required, but they're a perfect start for most applications.
|
*/
'defaults' => [
'guard' => 'web',
'passwords' => 'users',
],
/*
|--------------------------------------------------------------------------
| Authentication Guards
|--------------------------------------------------------------------------
|
| Next, you may define every authentication guard for your application.
| Of course, a great default configuration has been defined for you
| here which uses session storage and the Eloquent user provider.
|
| All authentication drivers have a user provider. This defines how the
| users are actually retrieved out of your database or other storage
| mechanisms used by this application to persist your user's data.
|
| Supported: "session", "token"
|
*/
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'ldap',
],
'api' => [
'driver' => 'passport',
'provider' => 'users',
'hash' => false,
],
],
/*
|--------------------------------------------------------------------------
| User Providers
|--------------------------------------------------------------------------
|
| All authentication drivers have a user provider. This defines how the
| users are actually retrieved out of your database or other storage
| mechanisms used by this application to persist your user's data.
|
| If you have multiple user tables or models you may configure multiple
| sources which represent each model / table. These sources may then
| be assigned to any extra authentication guards you have defined.
|
| Supported: "database", "eloquent"
|
*/
'providers' => [
'users' => [
'driver' => 'ldap',
'model' => App\Ldap\User::class,
],
// 'users' => [
// 'driver' => 'database',
// 'table' => 'users',
// ],
'ldap' => [
'driver' => 'ldap',
'model' => App\Ldap\User::class,
'rules' => [
App\Ldap\Rules\LoginObjectclassRule::class,
],
],
],
/*
|--------------------------------------------------------------------------
| Resetting Passwords
|--------------------------------------------------------------------------
|
| You may specify multiple password reset configurations if you have more
| than one user table or model in the application and you want to have
| separate password reset settings based on the specific user types.
|
| The expire time is the number of minutes that the reset token should be
| considered valid. This security feature keeps tokens short-lived so
| they have less time to be guessed. You may change this as needed.
|
*/
'passwords' => [
'users' => [
'provider' => 'users',
'table' => 'password_resets',
'expire' => 60,
'throttle' => 60,
],
],
/*
|--------------------------------------------------------------------------
| Password Confirmation Timeout
|--------------------------------------------------------------------------
|
| Here you may define the amount of seconds before a password confirmation
| times out and the user is prompted to re-enter their password via the
| confirmation screen. By default, the timeout lasts for three hours.
|
*/
'password_timeout' => 10800,
];

View File

@ -1,59 +0,0 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Default Broadcaster
|--------------------------------------------------------------------------
|
| This option controls the default broadcaster that will be used by the
| framework when an event needs to be broadcast. You may set this to
| any of the connections defined in the "connections" array below.
|
| Supported: "pusher", "redis", "log", "null"
|
*/
'default' => env('BROADCAST_DRIVER', 'null'),
/*
|--------------------------------------------------------------------------
| Broadcast Connections
|--------------------------------------------------------------------------
|
| Here you may define all of the broadcast connections that will be used
| to broadcast events to other systems or over websockets. Samples of
| each available type of connection are provided inside this array.
|
*/
'connections' => [
'pusher' => [
'driver' => 'pusher',
'key' => env('PUSHER_APP_KEY'),
'secret' => env('PUSHER_APP_SECRET'),
'app_id' => env('PUSHER_APP_ID'),
'options' => [
'cluster' => env('PUSHER_APP_CLUSTER'),
'useTLS' => true,
],
],
'redis' => [
'driver' => 'redis',
'connection' => 'default',
],
'log' => [
'driver' => 'log',
],
'null' => [
'driver' => 'null',
],
],
];

View File

@ -1,104 +0,0 @@
<?php
use Illuminate\Support\Str;
return [
/*
|--------------------------------------------------------------------------
| Default Cache Store
|--------------------------------------------------------------------------
|
| This option controls the default cache connection that gets used while
| using this caching library. This connection is used when another is
| not explicitly specified when executing a given caching function.
|
| Supported: "apc", "array", "database", "file",
| "memcached", "redis", "dynamodb"
|
*/
'default' => env('CACHE_DRIVER', 'file'),
/*
|--------------------------------------------------------------------------
| Cache Stores
|--------------------------------------------------------------------------
|
| Here you may define all of the cache "stores" for your application as
| well as their drivers. You may even define multiple stores for the
| same cache driver to group types of items stored in your caches.
|
*/
'stores' => [
'apc' => [
'driver' => 'apc',
],
'array' => [
'driver' => 'array',
'serialize' => false,
],
'database' => [
'driver' => 'database',
'table' => 'cache',
'connection' => null,
],
'file' => [
'driver' => 'file',
'path' => storage_path('framework/cache/data'),
],
'memcached' => [
'driver' => 'memcached',
'persistent_id' => env('MEMCACHED_PERSISTENT_ID'),
'sasl' => [
env('MEMCACHED_USERNAME'),
env('MEMCACHED_PASSWORD'),
],
'options' => [
// Memcached::OPT_CONNECT_TIMEOUT => 2000,
],
'servers' => [
[
'host' => env('MEMCACHED_HOST', '127.0.0.1'),
'port' => env('MEMCACHED_PORT', 11211),
'weight' => 100,
],
],
],
'redis' => [
'driver' => 'redis',
'connection' => 'cache',
],
'dynamodb' => [
'driver' => 'dynamodb',
'key' => env('AWS_ACCESS_KEY_ID'),
'secret' => env('AWS_SECRET_ACCESS_KEY'),
'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
'table' => env('DYNAMODB_CACHE_TABLE', 'cache'),
'endpoint' => env('DYNAMODB_ENDPOINT'),
],
],
/*
|--------------------------------------------------------------------------
| Cache Key Prefix
|--------------------------------------------------------------------------
|
| When utilizing a RAM based store such as APC or Memcached, there might
| be other applications utilizing the same cache. So, we'll specify a
| value to get prefixed to all our keys so we can avoid collisions.
|
*/
'prefix' => env('CACHE_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_cache'),
];

View File

@ -36,9 +36,9 @@
* version of phpLDAPadmin.
*/
/*********************************************
* Useful important configuration overrides *
*********************************************/
/*********************************************/
/* Useful important configuration overrides */
/*********************************************/
/* If you are asked to put PLA in debug mode, this is how you do it: */
# $config->custom->debug['level'] = 255;
@ -49,15 +49,11 @@
to a big random string. */
// $config->custom->session['blowfish'] = null;
/* If your auth_type is http, you can override your HTTP Authentication Realm. */
// $config->custom->session['http_realm'] = sprintf('%s %s',app_name(),'login');
/* The language setting. If you set this to 'auto', phpLDAPadmin will attempt
to determine your language automatically.
If PLA doesnt show (all) strings in your language, then you can do some
translation at http://translations.launchpad.net/phpldapadmin and download
the translation files, replacing those provided with PLA.
(We'll pick up the translations before making the next release too!) */
to determine your language automatically. Otherwise, available lanaguages
are: 'ct', 'de', 'en', 'es', 'fr', 'it', 'nl', and 'ru'
Localization is not complete yet, but most strings have been translated.
Please help by writing language files. See lang/en.php for an example. */
// $config->custom->appearance['language'] = 'auto';
/* The temporary storage directory where we will put jpegPhoto data
@ -84,9 +80,9 @@
// $config->custom->appearance['timezone'] = null;
# $config->custom->appearance['timezone'] = 'Australia/Melbourne';
/*********************************************
* Commands *
*********************************************/
/*********************************************/
/* Commands */
/*********************************************/
/* Command availability ; if you don't authorize a command the command
links will not be shown and the command action will not be permitted.
@ -142,9 +138,9 @@ $config->custom->commands['script'] = array(
);
*/
/*********************************************
* Appearance *
*********************************************/
/*********************************************/
/* Appearance */
/*********************************************/
/* If you want to choose the appearance of the tree, specify a class name which
inherits from the Tree class. */
@ -160,9 +156,6 @@ $config->custom->commands['script'] = array(
/* Hide the warnings for invalid objectClasses/attributes in templates. */
// $config->custom->appearance['hide_template_warning'] = false;
/* Set to true if you would like to hide header and footer parts. */
// $config->custom->appearance['minimalMode'] = false;
/* Configure what objects are shown in left hand tree */
// $config->custom->appearance['tree_filter'] = '(objectclass=*)';
@ -173,19 +166,9 @@ $config->custom->commands['script'] = array(
// $config->custom->appearance['tree_width'] = null;
# $config->custom->appearance['tree_width'] = 250;
/* Confirm create and update operations, allowing you to review the changes
and optionally skip attributes during the create/update operation. */
// $config->custom->confirm['create'] = true;
// $config->custom->confirm['update'] = true;
/* Confirm copy operations, and treat them like create operations. This allows
you to edit the attributes (thus changing any that might conflict with
uniqueness) before creating the new entry. */
// $config->custom->confirm['copy'] = true;
/*********************************************
* User-friendly attribute translation *
*********************************************/
/*********************************************/
/* User-friendly attribute translation */
/*********************************************/
/* Use this array to map attribute names to user friendly names. For example, if
you don't want to see "facsimileTelephoneNumber" but rather "Fax". */
@ -199,9 +182,9 @@ $config->custom->appearance['friendly_attrs'] = array(
'userPassword' => 'Password'
);
/*********************************************
* Hidden attributes *
*********************************************/
/*********************************************/
/* Hidden attributes */
/*********************************************/
/* You may want to hide certain attributes from being edited. If you want to
hide attributes from the user, you should use your LDAP servers ACLs.
@ -214,9 +197,9 @@ $config->custom->appearance['friendly_attrs'] = array(
// $config->custom->appearance['hide_attrs_exempt'] = null;
# $config->custom->appearance['hide_attrs_exempt'] = 'cn=PLA UnHide,ou=Groups,c=AU';
/*********************************************
* Read-only attributes *
*********************************************/
/*********************************************/
/* Read-only attributes */
/*********************************************/
/* You may want to phpLDAPadmin to display certain attributes as read only,
meaning that users will not be presented a form for modifying those
@ -230,12 +213,12 @@ $config->custom->appearance['friendly_attrs'] = array(
// $config->custom->appearance['readonly_attrs_exempt'] = null;
# $config->custom->appearance['readonly_attrs_exempt'] = 'cn=PLA ReadWrite,ou=Groups,c=AU';
/*********************************************
* Group attributes *
*********************************************/
/*********************************************/
/* Group attributes */
/*********************************************/
/* Add "modify group members" link to the attribute. */
// $config->custom->modify_member['groupattr'] = array('member','uniqueMember','memberUid','sudoUser');
// $config->custom->modify_member['groupattr'] = array('member','uniqueMember','memberUid');
/* Configure filter for member search. This only applies to "modify group members" feature */
// $config->custom->modify_member['filter'] = '(objectclass=Person)';
@ -243,15 +226,37 @@ $config->custom->appearance['friendly_attrs'] = array(
/* Attribute that is added to the group member attribute. */
// $config->custom->modify_member['attr'] = 'dn';
/* For Posix attributes */
// $config->custom->modify_member['posixattr'] = 'uid';
// $config->custom->modify_member['posixfilter'] = '(uid=*)';
// $config->custom->modify_member['posixgroupattr'] = 'memberUid';
/*********************************************
* Define your LDAP servers in this section *
*********************************************/
/*********************************************/
/* Support for attrs display order */
/*********************************************/
/* Use this array if you want to have your attributes displayed in a specific
order. You can use default attribute names or their fridenly names.
For example, "sn" will be displayed right after "givenName". All the other
attributes that are not specified in this array will be displayed after in
alphabetical order. */
// $config->custom->appearance['attr_display_order'] = array();
# $config->custom->appearance['attr_display_order'] = array(
# 'givenName',
# 'sn',
# 'cn',
# 'displayName',
# 'uid',
# 'uidNumber',
# 'gidNumber',
# 'homeDirectory',
# 'mail',
# 'userPassword'
# );
/*********************************************/
/* Define your LDAP servers in this section */
/*********************************************/
$servers = new Datastore();
@ -277,7 +282,7 @@ $servers->setValue('server','name','My LDAP Server');
auto-detect it for you. */
// $servers->setValue('server','base',array(''));
/* Five options for auth_type:
/* Four options for auth_type:
1. 'cookie': you will login via a web form, and a client-side cookie will
store your login dn and password.
2. 'session': same as cookie but your login dn and password are stored on the
@ -286,8 +291,6 @@ $servers->setValue('server','name','My LDAP Server');
HTTP authentication.
4. 'config': specify your login dn and password here in this config file. No
login will be required to use phpLDAPadmin for this server.
5. 'sasl': login will be taken from the webserver's kerberos authentication.
Currently only GSSAPI has been tested (using mod_auth_kerb).
Choose wisely to protect your authentication information appropriately for
your situation. If you choose 'cookie', your cookie contents will be
@ -296,11 +299,10 @@ $servers->setValue('server','name','My LDAP Server');
// $servers->setValue('login','auth_type','session');
/* The DN of the user for phpLDAPadmin to bind with. For anonymous binds or
'cookie','session' or 'sasl' auth_types, LEAVE THE LOGIN_DN AND LOGIN_PASS
BLANK. If you specify a login_attr in conjunction with a cookie or session
auth_type, then you can also specify the bind_id/bind_pass here for searching
the directory for users (ie, if your LDAP server does not allow anonymous
binds. */
'cookie' or 'session' auth_types, LEAVE THE LOGIN_DN AND LOGIN_PASS BLANK. If
you specify a login_attr in conjunction with a cookie or session auth_type,
then you can also specify the bind_id/bind_pass here for searching the
directory for users (ie, if your LDAP server does not allow anonymous binds. */
// $servers->setValue('login','bind_id','');
# $servers->setValue('login','bind_id','cn=Manager,dc=example,dc=com');
@ -319,27 +321,22 @@ $servers->setValue('server','name','My LDAP Server');
/* Enable SASL authentication LDAP SASL authentication requires PHP 5.x
configured with --with-ldap-sasl=DIR. If this option is disabled (ie, set to
false), then all other sasl options are ignored. */
# $servers->setValue('login','auth_type','sasl');
// $servers->setValue('server','sasl_auth',false);
/* SASL GSSAPI auth mechanism (requires auth_type of sasl) */
// $servers->setValue('sasl','mech','GSSAPI');
/* SASL PLAIN support... this mech converts simple binds to SASL
PLAIN binds using any auth_type (or other bind_id/pass) as credentials.
NOTE: auth_type must be simple auth compatible (ie not sasl) */
# $servers->setValue('sasl','mech','PLAIN');
/* SASL auth mechanism */
// $servers->setValue('server','sasl_mech','PLAIN');
/* SASL authentication realm name */
// $servers->setValue('sasl','realm','');
# $servers->setValue('sasl','realm','EXAMPLE.COM');
// $servers->setValue('server','sasl_realm','');
# $servers->setValue('server','sasl_realm','example.com');
/* SASL authorization ID name
If this option is undefined, authorization id will be computed from bind DN,
using authz_id_regex and authz_id_replacement. */
// $servers->setValue('sasl','authz_id', null);
using sasl_authz_id_regex and sasl_authz_id_replacement. */
// $servers->setValue('server','sasl_authz_id', null);
/* SASL authorization id regex and replacement
When authz_id property is not set (default), phpLDAPAdmin will try to
When sasl_authz_id property is not set (default), phpLDAPAdmin will try to
figure out authorization id by itself from bind distinguished name (DN).
This procedure is done by calling preg_replace() php function in the
@ -351,18 +348,18 @@ $servers->setValue('server','name','My LDAP Server');
For info about pcre regexes, see:
- pcre(3), perlre(3)
- http://www.php.net/preg_replace */
// $servers->setValue('sasl','authz_id_regex',null);
// $servers->setValue('sasl','authz_id_replacement',null);
# $servers->setValue('sasl','authz_id_regex','/^uid=([^,]+)(.+)/i');
# $servers->setValue('sasl','authz_id_replacement','$1');
// $servers->setValue('server','sasl_authz_id_regex',null);
// $servers->setValue('server','sasl_authz_id_replacement',null);
# $servers->setValue('server','sasl_authz_id_regex','/^uid=([^,]+)(.+)/i');
# $servers->setValue('server','sasl_authz_id_replacement','$1');
/* SASL auth security props.
See http://beepcore-tcl.sourceforge.net/tclsasl.html#anchor5 for explanation. */
// $servers->setValue('sasl','props',null);
// $servers->setValue('server','sasl_props',null);
/* Default password hashing algorithm. One of md5, ssha, sha, md5crpyt, smd5,
blowfish, crypt or leave blank for now default algorithm. */
// $servers->setValue('appearance','pla_password_hash','md5');
// $servers->setValue('appearance','password_hash','md5');
/* If you specified 'cookie' or 'session' as the auth_type above, you can
optionally specify here an attribute to use when logging in. If you enter
@ -370,18 +367,18 @@ $servers->setValue('server','name','My LDAP Server');
and log in as that user.
Leave blank or specify 'dn' to use full DN for logging in. Note also that if
your LDAP server requires you to login to perform searches, you can enter the
DN to use when searching in 'bind_id' and 'bind_pass' above. */
DN to use when searching in 'bind_id' and 'bind_pass' above.
// $servers->setValue('login','attr','dn');
/* Base DNs to used for logins. If this value is not set, then the LDAP server
Base DNs are used. */
// $servers->setValue('login','base',array());
/* If login_attr was set to 'dn', it is possible to specify a template string to
build the DN from. Use '%s' where user input should be inserted. A user may
still enter the complete DN. In this case the template will not be used. */
// $servers->setValue('login','bind_dn_template',null);
# $servers->setValue('login','bind_dn_template','cn=%s,ou=people,dc=example,dc=com');
/* If 'login,attr' is used above such that phpLDAPadmin will search for your DN
at login, you may restrict the search to a specific objectClasses. EG, set this
to array('posixAccount') or array('inetOrgPerson',..), depending upon your
setup. */
// $servers->setValue('login','class',array());
/* If you specified something different from 'dn', for example 'uid', as the
login_attr above, you can optionally specify here to fall back to
@ -400,12 +397,6 @@ $servers->setValue('server','name','My LDAP Server');
in the tree viewer. */
// $servers->setValue('appearance','show_create',true);
/* Set to true if you would like to initially open the first level of each tree. */
// $servers->setValue('appearance','open_tree',false);
/* Set to true to display authorization ID in place of login dn (PHP 7.2+) */
// $servers->setValue('appearance','show_authz',false);
/* This feature allows phpLDAPadmin to automatically determine the next
available uidNumber for a new entry. */
// $servers->setValue('auto_number','enable',true);
@ -422,7 +413,7 @@ $servers->setValue('server','name','My LDAP Server');
# $servers->setValue('auto_number','search_base','ou=People,dc=example,dc=com');
/* The minimum number to use when searching for the next available number
(only when 'search' is used for auto_number. */
(only when 'search' is used for auto_number */
// $servers->setValue('auto_number','min',array('uidNumber'=>1000,'gidNumber'=>500));
/* If you set this, then phpldapadmin will bind to LDAP with this user ID when
@ -454,18 +445,13 @@ $servers->setValue('server','name','My LDAP Server');
/* Set this if you dont want this LDAP server to show in the tree */
// $servers->setValue('server','visible',true);
/* Set this if you want to hide the base DNs that dont exist instead of
displaying the message "The base entry doesnt exist, create it?"
// $servers->setValue('server','hide_noaccess_base',false);
# $servers->setValue('server','hide_noaccess_base',true);
/* This is the time out value in minutes for the server. After as many minutes
of inactivity you will be automatically logged out. If not set, the default
value will be ( session_cache_expire()-1 ) */
# $servers->setValue('login','timeout',30);
/* Set this if you want phpldapadmin to perform rename operation on entry which
has children. Certain servers are known to allow it, certain are not. */
has children. Certain servers are known to allow it, certain are not */
// $servers->setValue('server','branch_rename',false);
/* If you set this, then phpldapadmin will show these attributes as
@ -478,9 +464,18 @@ $servers->setValue('server','name','My LDAP Server');
// $servers->setValue('server','custom_attrs',array(''));
# $servers->setValue('server','custom_attrs',array('nsRoleDN','nsRole','nsAccountLock'));
/*********************************************
* Unique attributes *
*********************************************/
/* These attributes will be forced to MAY attributes and become option in the
templates. If they are not defined in the templates, then they wont appear
as per normal template processing. You may want to do this becuase your LDAP
server may automatically calculate a default value.
In Fedora Directory Server using the DNA Plugin one could ignore uidNumber,
gidNumber and sambaSID. */
// $servers->setValue('force_may','attrs',array(''));
# $servers->setValue('force_may','attrs',array('uidNumber','gidNumber','sambaSID'));
/*********************************************/
/* Unique attributes */
/*********************************************/
/* You may want phpLDAPadmin to enforce some attributes to have unique values
(ie: not belong to other entries in your tree. This (together with
@ -515,15 +510,15 @@ $servers->setValue('login','bind_pass','');
$servers->setValue('server','tls',false);
# SASL auth
$servers->setValue('login','auth_type','sasl');
$servers->setValue('sasl','mech','GSSAPI');
$servers->setValue('sasl','realm','EXAMPLE.COM');
$servers->setValue('sasl','authz_id',null);
$servers->setValue('sasl','authz_id_regex','/^uid=([^,]+)(.+)/i');
$servers->setValue('sasl','authz_id_replacement','$1');
$servers->setValue('sasl','props',null);
$servers->setValue('server','sasl_auth',true);
$servers->setValue('server','sasl_mech','PLAIN');
$servers->setValue('server','sasl_realm','EXAMPLE.COM');
$servers->setValue('server','sasl_authz_id',null);
$servers->setValue('server','sasl_authz_id_regex','/^uid=([^,]+)(.+)/i');
$servers->setValue('server','sasl_authz_id_replacement','$1');
$servers->setValue('server','sasl_props',null);
$servers->setValue('appearance','pla_password_hash','md5');
$servers->setValue('appearance','password_hash','md5');
$servers->setValue('login','attr','dn');
$servers->setValue('login','fallback_dn',false);
$servers->setValue('login','class',null);
@ -548,21 +543,6 @@ $servers->setValue('login','timeout',30);
$servers->setValue('server','branch_rename',false);
$servers->setValue('server','custom_sys_attrs',array('passwordExpirationTime','passwordAllowChangeTime'));
$servers->setValue('server','custom_attrs',array('nsRoleDN','nsRole','nsAccountLock'));
$servers->setValue('server','force_may',array('uidNumber','gidNumber','sambaSID'));
$servers->setValue('force_may','attrs',array('uidNumber','gidNumber','sambaSID'));
*/
/***********************************************************************************
* If you want to configure Google reCAPTCHA on autentication form, do so below. *
* Remove the commented lines and use this section as a template for all *
* reCAPTCHA v2 Generate on https://www.google.com/recaptcha/ *
* *
* IMPORTANT: Select reCAPTCHA v2 on Type of reCAPTCHA *
***********************************************************************************/
$config->custom->session['reCAPTCHA-enable'] = false;
$config->custom->session['reCAPTCHA-key-site'] = '<put-here-key-site>';
$config->custom->session['reCAPTCHA-key-server'] = '<put-here-key-server>';
?>

View File

@ -1,34 +0,0 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Cross-Origin Resource Sharing (CORS) Configuration
|--------------------------------------------------------------------------
|
| Here you may configure your settings for cross-origin resource sharing
| or "CORS". This determines what cross-origin operations may execute
| in web browsers. You are free to adjust these settings as needed.
|
| To learn more: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
|
*/
'paths' => ['api/*', 'sanctum/csrf-cookie'],
'allowed_methods' => ['*'],
'allowed_origins' => ['*'],
'allowed_origins_patterns' => [],
'allowed_headers' => ['*'],
'exposed_headers' => [],
'max_age' => 0,
'supports_credentials' => false,
];

View File

@ -1,147 +0,0 @@
<?php
use Illuminate\Support\Str;
return [
/*
|--------------------------------------------------------------------------
| Default Database Connection Name
|--------------------------------------------------------------------------
|
| Here you may specify which of the database connections below you wish
| to use as your default connection for all database work. Of course
| you may use many connections at once using the Database library.
|
*/
'default' => env('DB_CONNECTION', 'mysql'),
/*
|--------------------------------------------------------------------------
| Database Connections
|--------------------------------------------------------------------------
|
| Here are each of the database connections setup for your application.
| Of course, examples of configuring each database platform that is
| supported by Laravel is shown below to make development simple.
|
|
| All database work in Laravel is done through the PHP PDO facilities
| so make sure you have the driver for your particular database of
| choice installed on your machine before you begin development.
|
*/
'connections' => [
'sqlite' => [
'driver' => 'sqlite',
'url' => env('DATABASE_URL'),
'database' => env('DB_DATABASE', database_path('database.sqlite')),
'prefix' => '',
'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true),
],
'mysql' => [
'driver' => 'mysql',
'url' => env('DATABASE_URL'),
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '3306'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'unix_socket' => env('DB_SOCKET', ''),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'prefix_indexes' => true,
'strict' => true,
'engine' => null,
'options' => extension_loaded('pdo_mysql') ? array_filter([
PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
]) : [],
],
'pgsql' => [
'driver' => 'pgsql',
'url' => env('DATABASE_URL'),
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '5432'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'charset' => 'utf8',
'prefix' => '',
'prefix_indexes' => true,
'schema' => 'public',
'sslmode' => 'prefer',
],
'sqlsrv' => [
'driver' => 'sqlsrv',
'url' => env('DATABASE_URL'),
'host' => env('DB_HOST', 'localhost'),
'port' => env('DB_PORT', '1433'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'charset' => 'utf8',
'prefix' => '',
'prefix_indexes' => true,
],
],
/*
|--------------------------------------------------------------------------
| Migration Repository Table
|--------------------------------------------------------------------------
|
| This table keeps track of all the migrations that have already run for
| your application. Using this information, we can determine which of
| the migrations on disk haven't actually been run in the database.
|
*/
'migrations' => 'migrations',
/*
|--------------------------------------------------------------------------
| Redis Databases
|--------------------------------------------------------------------------
|
| Redis is an open source, fast, and advanced key-value store that also
| provides a richer body of commands than a typical key-value system
| such as APC or Memcached. Laravel makes it easy to dig right in.
|
*/
'redis' => [
'client' => env('REDIS_CLIENT', 'phpredis'),
'options' => [
'cluster' => env('REDIS_CLUSTER', 'redis'),
'prefix' => env('REDIS_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_database_'),
],
'default' => [
'url' => env('REDIS_URL'),
'host' => env('REDIS_HOST', '127.0.0.1'),
'password' => env('REDIS_PASSWORD', null),
'port' => env('REDIS_PORT', '6379'),
'database' => env('REDIS_DB', '0'),
],
'cache' => [
'url' => env('REDIS_URL'),
'host' => env('REDIS_HOST', '127.0.0.1'),
'password' => env('REDIS_PASSWORD', null),
'port' => env('REDIS_PORT', '6379'),
'database' => env('REDIS_CACHE_DB', '1'),
],
],
];

View File

@ -1,85 +0,0 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Default Filesystem Disk
|--------------------------------------------------------------------------
|
| Here you may specify the default filesystem disk that should be used
| by the framework. The "local" disk, as well as a variety of cloud
| based disks are available to your application. Just store away!
|
*/
'default' => env('FILESYSTEM_DRIVER', 'local'),
/*
|--------------------------------------------------------------------------
| Default Cloud Filesystem Disk
|--------------------------------------------------------------------------
|
| Many applications store files both locally and in the cloud. For this
| reason, you may specify a default "cloud" driver here. This driver
| will be bound as the Cloud disk implementation in the container.
|
*/
'cloud' => env('FILESYSTEM_CLOUD', 's3'),
/*
|--------------------------------------------------------------------------
| Filesystem Disks
|--------------------------------------------------------------------------
|
| Here you may configure as many filesystem "disks" as you wish, and you
| may even configure multiple disks of the same driver. Defaults have
| been setup for each driver as an example of the required options.
|
| Supported Drivers: "local", "ftp", "sftp", "s3"
|
*/
'disks' => [
'local' => [
'driver' => 'local',
'root' => storage_path('app'),
],
'public' => [
'driver' => 'local',
'root' => storage_path('app/public'),
'url' => env('APP_URL').'/storage',
'visibility' => 'public',
],
's3' => [
'driver' => 's3',
'key' => env('AWS_ACCESS_KEY_ID'),
'secret' => env('AWS_SECRET_ACCESS_KEY'),
'region' => env('AWS_DEFAULT_REGION'),
'bucket' => env('AWS_BUCKET'),
'url' => env('AWS_URL'),
'endpoint' => env('AWS_ENDPOINT'),
],
],
/*
|--------------------------------------------------------------------------
| Symbolic Links
|--------------------------------------------------------------------------
|
| Here you may configure the symbolic links that will be created when the
| `storage:link` Artisan command is executed. The array keys should be
| the locations of the links and the values should be their targets.
|
*/
'links' => [
public_path('storage') => storage_path('app/public'),
],
];

Some files were not shown because too many files have changed in this diff Show More