├── .dockerignore ├── .editorconfig ├── .env.example ├── .env.testing ├── .gitattributes ├── .gitea └── workflows │ └── build_docker.yaml ├── .github ├── FUNDING.yml └── ISSUE_TEMPLATE │ ├── bug_report.md │ └── config.yml ├── .gitignore ├── LICENSE ├── README.md ├── VERSION ├── app ├── .gitignore ├── Classes │ └── LDAP │ │ ├── Attribute.php │ │ ├── Attribute │ │ ├── Binary.php │ │ ├── Binary │ │ │ └── JpegPhoto.php │ │ ├── Certificate.php │ │ ├── CertificateList.php │ │ ├── Factory.php │ │ ├── GidNumber.php │ │ ├── Internal.php │ │ ├── Internal │ │ │ └── Timestamp.php │ │ ├── KrbPrincipalKey.php │ │ ├── KrbTicketFlags.php │ │ ├── NoAttrTags │ │ │ └── Generic.php │ │ ├── ObjectClass.php │ │ ├── Password.php │ │ ├── Password │ │ │ ├── Argon2i.php │ │ │ ├── Argon2id.php │ │ │ ├── Base.php │ │ │ ├── Bcrypt.php │ │ │ ├── Blowfish.php │ │ │ ├── Clear.php │ │ │ ├── Crypt.php │ │ │ ├── ExtDes.php │ │ │ ├── MD5.php │ │ │ ├── MD5crypt.php │ │ │ ├── SASL.php │ │ │ ├── SHA.php │ │ │ ├── SHA256.php │ │ │ ├── SHA256crypt.php │ │ │ ├── SHA384.php │ │ │ ├── SHA512.php │ │ │ ├── SHA512crypt.php │ │ │ ├── SMD5.php │ │ │ ├── SSHA.php │ │ │ ├── SSHA256.php │ │ │ ├── SSHA384.php │ │ │ └── SSHA512.php │ │ ├── RDN.php │ │ ├── Schema.php │ │ └── Schema │ │ │ ├── Generic.php │ │ │ ├── Mechanisms.php │ │ │ └── OID.php │ │ ├── Export.php │ │ ├── Export │ │ └── LDIF.php │ │ ├── Import.php │ │ ├── Import │ │ └── LDIF.php │ │ ├── Schema │ │ ├── AttributeType.php │ │ ├── Base.php │ │ ├── LDAPSyntax.php │ │ ├── MatchingRule.php │ │ ├── MatchingRuleUse.php │ │ ├── ObjectClass.php │ │ └── ObjectClassAttribute.php │ │ └── Server.php ├── Exceptions │ ├── Import │ │ ├── AttributeException.php │ │ ├── GeneralException.php │ │ ├── ObjectExistsException.php │ │ └── VersionException.php │ └── InvalidUsage.php ├── Http │ ├── Controllers │ │ ├── AjaxController.php │ │ ├── Auth │ │ │ └── LoginController.php │ │ ├── Controller.php │ │ ├── HomeController.php │ │ └── SearchController.php │ ├── Middleware │ │ ├── AllowAnonymous.php │ │ ├── ApplicationSession.php │ │ ├── CheckUpdate.php │ │ ├── SwapinAuthUser.php │ │ └── ViewVariables.php │ └── Requests │ │ ├── EntryAddRequest.php │ │ ├── EntryRequest.php │ │ └── ImportRequest.php ├── Ldap │ ├── Entry.php │ ├── Guard.php │ ├── LdapUserRepository.php │ ├── Rules │ │ └── LoginObjectclassRule.php │ └── User.php ├── Providers │ └── AppServiceProvider.php ├── Rules │ ├── DNExists.php │ └── HasStructuralObjectClass.php ├── Traits │ └── MD5Updates.php ├── View │ └── Components │ │ └── Attribute.php └── helpers.php ├── artisan ├── bootstrap ├── app.php ├── cache │ └── .gitignore └── providers.php ├── composer.json ├── composer.lock ├── config ├── app.php ├── auth.php ├── cache.php ├── ldap.php ├── ldap_supported_oids.txt ├── ldap_supported_saslmechanisms.txt ├── logging.php ├── pla.php └── session.php ├── database └── .gitignore ├── docker ├── Dockerfile └── init-docker ├── package-lock.json ├── package.json ├── phpunit.xml ├── public ├── .htaccess ├── VERSION ├── css │ ├── custom.css │ ├── fixes.css │ ├── flags │ │ ├── flags16-both.css │ │ ├── flags16.png │ │ ├── flags32-both.css │ │ └── flags32.png │ └── print.css ├── favicon.ico ├── images │ ├── logo-h-lg.png │ ├── logo-h.png │ └── logo.png ├── index.php ├── js │ └── custom.js └── robots.txt ├── resources ├── images │ └── user-secret-solid.svg ├── js │ ├── app.js │ ├── bootstrap.js │ └── bootstrap3-typeahead.js ├── lang │ ├── README.md │ ├── dev.json │ └── en │ │ ├── auth.php │ │ ├── pagination.php │ │ ├── passwords.php │ │ └── validation.php ├── sass │ ├── _variables.scss │ └── app.scss ├── themes │ └── architect │ │ ├── src │ │ ├── app.js │ │ ├── base.scss │ │ ├── components │ │ │ ├── bootstrap5 │ │ │ │ ├── _alert.scss │ │ │ │ ├── _badge.scss │ │ │ │ ├── _breadcrumb.scss │ │ │ │ ├── _button-group.scss │ │ │ │ ├── _buttons.scss │ │ │ │ ├── _card.scss │ │ │ │ ├── _close.scss │ │ │ │ ├── _containers.scss │ │ │ │ ├── _dropdown.scss │ │ │ │ ├── _forms.scss │ │ │ │ ├── _functions.scss │ │ │ │ ├── _grid.scss │ │ │ │ ├── _helpers.scss │ │ │ │ ├── _images.scss │ │ │ │ ├── _list-group.scss │ │ │ │ ├── _maps.scss │ │ │ │ ├── _mixins.scss │ │ │ │ ├── _modal.scss │ │ │ │ ├── _nav.scss │ │ │ │ ├── _navbar.scss │ │ │ │ ├── _pagination.scss │ │ │ │ ├── _reboot.scss │ │ │ │ ├── _root.scss │ │ │ │ ├── _tables.scss │ │ │ │ ├── _tooltip.scss │ │ │ │ ├── _transitions.scss │ │ │ │ ├── _type.scss │ │ │ │ ├── _utilities.scss │ │ │ │ ├── _variables-dark.scss │ │ │ │ ├── _variables.scss │ │ │ │ ├── bootstrap-grid.scss │ │ │ │ ├── bootstrap-reboot.scss │ │ │ │ ├── bootstrap-utilities.scss │ │ │ │ ├── bootstrap.scss │ │ │ │ ├── forms │ │ │ │ │ ├── _floating-labels.scss │ │ │ │ │ ├── _form-check.scss │ │ │ │ │ ├── _form-control.scss │ │ │ │ │ ├── _form-range.scss │ │ │ │ │ ├── _form-select.scss │ │ │ │ │ ├── _form-text.scss │ │ │ │ │ ├── _input-group.scss │ │ │ │ │ ├── _labels.scss │ │ │ │ │ └── _validation.scss │ │ │ │ ├── helpers │ │ │ │ │ ├── _clearfix.scss │ │ │ │ │ ├── _color-bg.scss │ │ │ │ │ ├── _colored-links.scss │ │ │ │ │ ├── _focus-ring.scss │ │ │ │ │ ├── _icon-link.scss │ │ │ │ │ ├── _position.scss │ │ │ │ │ ├── _ratio.scss │ │ │ │ │ ├── _stacks.scss │ │ │ │ │ ├── _stretched-link.scss │ │ │ │ │ ├── _text-truncation.scss │ │ │ │ │ ├── _visually-hidden.scss │ │ │ │ │ └── _vr.scss │ │ │ │ ├── mixins │ │ │ │ │ ├── _alert.scss │ │ │ │ │ ├── _backdrop.scss │ │ │ │ │ ├── _banner.scss │ │ │ │ │ ├── _border-radius.scss │ │ │ │ │ ├── _box-shadow.scss │ │ │ │ │ ├── _breakpoints.scss │ │ │ │ │ ├── _buttons.scss │ │ │ │ │ ├── _caret.scss │ │ │ │ │ ├── _clearfix.scss │ │ │ │ │ ├── _color-mode.scss │ │ │ │ │ ├── _color-scheme.scss │ │ │ │ │ ├── _container.scss │ │ │ │ │ ├── _deprecate.scss │ │ │ │ │ ├── _forms.scss │ │ │ │ │ ├── _gradients.scss │ │ │ │ │ ├── _grid.scss │ │ │ │ │ ├── _image.scss │ │ │ │ │ ├── _list-group.scss │ │ │ │ │ ├── _lists.scss │ │ │ │ │ ├── _pagination.scss │ │ │ │ │ ├── _reset-text.scss │ │ │ │ │ ├── _resize.scss │ │ │ │ │ ├── _table-variants.scss │ │ │ │ │ ├── _text-truncate.scss │ │ │ │ │ ├── _transition.scss │ │ │ │ │ ├── _utilities.scss │ │ │ │ │ └── _visually-hidden.scss │ │ │ │ ├── utilities │ │ │ │ │ └── _api.scss │ │ │ │ └── vendor │ │ │ │ │ └── _rfs.scss │ │ │ ├── hamburgers │ │ │ │ ├── _base.scss │ │ │ │ ├── hamburgers.scss │ │ │ │ └── types │ │ │ │ │ └── _elastic.scss │ │ │ ├── icons │ │ │ │ ├── _p7icons.scss │ │ │ │ └── fontawesome │ │ │ │ │ └── _fontawesome.scss │ │ │ ├── popovers-tooltips │ │ │ │ └── _popovers-tooltips.scss │ │ │ └── tables │ │ │ │ ├── _datatables.scss │ │ │ │ └── _tables.scss │ │ ├── elements │ │ │ ├── _badges.scss │ │ │ ├── _buttons.scss │ │ │ ├── _cards.scss │ │ │ ├── _dropdown.scss │ │ │ ├── _forms.scss │ │ │ ├── _modals.scss │ │ │ ├── _navs.scss │ │ │ ├── _pagination.scss │ │ │ ├── _tabs.scss │ │ │ └── listgroup.scss │ │ ├── init.js │ │ ├── layout │ │ │ ├── _layout-variables.scss │ │ │ ├── _layout.scss │ │ │ ├── elements │ │ │ │ ├── page-title │ │ │ │ │ └── _page-title-base.scss │ │ │ │ └── search-box │ │ │ │ │ └── _search-box.scss │ │ │ ├── footer │ │ │ │ └── _footer-base.scss │ │ │ ├── generic │ │ │ │ ├── _animations.scss │ │ │ │ └── _generic-base.scss │ │ │ ├── header │ │ │ │ ├── _header-base.scss │ │ │ │ ├── modifiers │ │ │ │ │ └── _fixed-header.scss │ │ │ │ └── themes │ │ │ │ │ ├── _header-dark.scss │ │ │ │ │ └── _header-light.scss │ │ │ ├── main │ │ │ │ ├── _main-base.scss │ │ │ │ └── themes │ │ │ │ │ └── _main-white.scss │ │ │ ├── responsive │ │ │ │ └── _responsive-base.scss │ │ │ └── sidebar │ │ │ │ ├── _sidebar-base.scss │ │ │ │ ├── modifiers │ │ │ │ ├── _closed-sidebar.scss │ │ │ │ ├── _fixed-sidebar.scss │ │ │ │ └── _navmenu-vertical.scss │ │ │ │ └── themes │ │ │ │ ├── _sidebar-dark.scss │ │ │ │ └── _sidebar-light.scss │ │ ├── themes │ │ │ ├── _layout-variables.scss │ │ │ └── default │ │ │ │ └── _variables.scss │ │ ├── utils │ │ │ ├── _animate-override.scss │ │ │ ├── _animate.scss │ │ │ ├── _backgrounds.scss │ │ │ ├── _comps-animations.scss │ │ │ ├── _helpers.scss │ │ │ └── helpers │ │ │ │ ├── _grayscale.scss │ │ │ │ └── _opacity.scss │ │ └── widgets │ │ │ └── content-boxes │ │ │ └── _content-boxes.scss │ │ └── views │ │ ├── auth │ │ ├── login.blade.php │ │ └── partials │ │ │ └── scripts.blade.php │ │ └── layouts │ │ ├── app.blade.php │ │ ├── auth.blade.php │ │ ├── error.blade.php │ │ └── partials │ │ ├── contentfooter.blade.php │ │ ├── contentheader.blade.php │ │ ├── htmlheader.blade.php │ │ ├── scripts.blade.php │ │ ├── sidebarmenu.blade.php │ │ └── topmenu.blade.php └── views │ ├── components │ ├── alert │ │ └── attribute_tags_cant_manage.blade.php │ ├── attribute-type.blade.php │ ├── attribute.blade.php │ ├── attribute │ │ ├── binary │ │ │ └── jpegphoto.blade.php │ │ ├── internal.blade.php │ │ ├── internal │ │ │ └── timestamp.blade.php │ │ ├── krblastfailedauth.blade.php │ │ ├── krblastpwdchange.blade.php │ │ ├── krblastsuccessfulauth.blade.php │ │ ├── krbloginfailedcount.blade.php │ │ ├── krbpasswordexpiration.blade.php │ │ ├── krbprincipalkey.blade.php │ │ ├── krbticketflags.blade.php │ │ ├── layout.blade.php │ │ ├── objectclass.blade.php │ │ ├── password.blade.php │ │ ├── rdn.blade.php │ │ ├── schema │ │ │ ├── generic.blade.php │ │ │ ├── mechanisms.blade.php │ │ │ └── oid.blade.php │ │ └── widget │ │ │ ├── objectclass.blade.php │ │ │ └── options.blade.php │ ├── error.blade.php │ ├── failed.blade.php │ ├── file-note.blade.php │ ├── form │ │ ├── base.blade.php │ │ ├── cancel.blade.php │ │ ├── disabled │ │ │ ├── datetime.blade.php │ │ │ └── input.blade.php │ │ ├── reset.blade.php │ │ ├── select.blade.php │ │ └── submit.blade.php │ ├── modal │ │ └── close.blade.php │ ├── note.blade.php │ ├── success.blade.php │ ├── syntax │ │ ├── certificate.blade.php │ │ └── certificatelist.blade.php │ └── updated.blade.php │ ├── debug.blade.php │ ├── errors │ ├── 401.blade.php │ ├── 555.blade.php │ ├── 597.blade.php │ ├── 598.blade.php │ └── 599.blade.php │ ├── fragment │ ├── dn │ │ ├── add_attr.blade.php │ │ └── header.blade.php │ ├── export.blade.php │ └── schema │ │ ├── attributetypes.blade.php │ │ ├── ldapsyntaxes.blade.php │ │ ├── matchingrules.blade.php │ │ └── objectclasses.blade.php │ ├── frame.blade.php │ ├── frames │ ├── create.blade.php │ ├── dn.blade.php │ ├── import.blade.php │ ├── import_result.blade.php │ ├── info.blade.php │ └── schema.blade.php │ ├── home.blade.php │ ├── layouts │ └── dn.blade.php │ ├── modals │ ├── entry-delete.blade.php │ ├── entry-export.blade.php │ └── entry-userpassword-check.blade.php │ └── update.blade.php ├── routes └── web.php ├── storage ├── app │ ├── .gitignore │ └── public │ │ └── .gitignore ├── framework │ ├── .gitignore │ ├── cache │ │ ├── .gitignore │ │ └── data │ │ │ └── .gitignore │ ├── sessions │ │ └── .gitignore │ ├── testing │ │ └── .gitignore │ └── views │ │ └── .gitignore └── logs │ └── .gitignore ├── tests ├── CreatesApplication.php ├── Feature │ ├── AttributeTagsTest.php │ ├── ExampleTest.php │ ├── GetBaseDNTest.php │ ├── ImportTest.php │ ├── LoginTest.php │ └── data │ │ └── ldif-import.ldif ├── TestCase.php ├── Unit │ └── ExampleTest.php └── server │ └── openldap │ ├── bases │ ├── 21-example.com.ldif │ ├── 22-example_com.ldif │ ├── 23-flintstones.ldif │ ├── 24-simpsons.ldif │ └── 25-test.ldif │ ├── data │ ├── 01-au.ldif │ ├── 03-example.com.ldif │ ├── 04-example_com.ldif │ ├── 04-z_kerberos.ldif │ ├── 04-z_labeleduri.ldif │ ├── 04-z_usercert.ldif │ ├── 05-flintstones.ldif │ ├── 06-simpsons.ldif │ ├── 07-test-01.ldif │ ├── 07-test-il8n.ldif │ └── 07-test.ldif │ └── schema │ ├── add │ ├── 30-kerberos.ldif │ ├── 30-sudorole.ldif │ └── 30-uidpool.ldif │ └── modify │ ├── 00-config.ldif │ ├── 00-mapsize.ldif │ ├── 00-sizelimit.ldif │ ├── 40-dynlist-options.ldif │ └── 99-argon.ldif └── webpack.mix.js /.dockerignore: -------------------------------------------------------------------------------- 1 | .dockerignore 2 | .editorconfig 3 | .env.testing 4 | .idea 5 | .git* 6 | .phpunit.result.cache 7 | .styleci.yml 8 | node_modules/ 9 | package.json 10 | package-lock.json 11 | phpunit.xml 12 | vendor/ 13 | webpack.mix.js 14 | yarn.lock 15 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | indent_size = 4 7 | indent_style = tab 8 | insert_final_newline = false 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | 14 | [*.{yml,yaml}] 15 | indent_size = 2 16 | 17 | [docker-compose.yml] 18 | indent_size = 4 19 | -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | APP_NAME=Laravel 2 | APP_ENV=production 3 | APP_KEY= 4 | APP_DEBUG=false 5 | APP_URL=http://localhost 6 | 7 | LOG_CHANNEL=daily 8 | 9 | CACHE_DRIVER=file 10 | QUEUE_CONNECTION=sync 11 | SESSION_DRIVER=file 12 | SESSION_LIFETIME=120 13 | 14 | LDAP_HOST= 15 | LDAP_BASE_DN= 16 | LDAP_USERNAME= 17 | LDAP_PASSWORD= 18 | LDAP_CACHE=false 19 | -------------------------------------------------------------------------------- /.env.testing: -------------------------------------------------------------------------------- 1 | APP_NAME=Laravel 2 | APP_ENV=local 3 | APP_KEY= 4 | APP_DEBUG=true 5 | APP_URL=http://localhost 6 | 7 | LOG_CHANNEL=stderr 8 | 9 | CACHE_DRIVER=array 10 | QUEUE_CONNECTION=sync 11 | SESSION_DRIVER=file 12 | SESSION_LIFETIME=120 13 | 14 | LDAP_HOST=openldap 15 | LDAP_BASE_DN="dc=Test" 16 | LDAP_USERNAME="cn=admin,dc=Test" 17 | LDAP_PASSWORD="test" 18 | LDAP_CACHE=false 19 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | *.css linguist-vendored 3 | *.scss linguist-vendored 4 | *.js linguist-vendored 5 | CHANGELOG.md export-ignore 6 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [leenooks] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry 13 | custom: ['https://www.buymeacoffee.com/dege'] 14 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. (One issue per report please.) 12 | 13 | **Version of PLA** 14 | What version of PLA are you using. Are you using the docker container, an distribution package or running from GIT source? 15 | 16 | **To Reproduce** 17 | Steps to reproduce the behavior: 18 | 1. Go to '...' 19 | 2. Click on '....' 20 | 3. Scroll down to '....' 21 | 4. See error 22 | 23 | **Expected behavior** 24 | A clear and concise description of what you expected to happen. 25 | 26 | **Screenshots** 27 | If applicable, add screenshots to help explain your problem. Also include any logs or backtrace information 28 | 29 | **LDAP Server details (please complete the following information):** 30 | - OS: [e.g. iOS] 31 | - Server Name [e.g. OpenLDAP, Windows AD,...] 32 | - Version [e.g. 22] 33 | 34 | **Smartphone (please complete the following information):** 35 | - Device: [e.g. iPhone6] 36 | - OS: [e.g. iOS8.1] 37 | - Browser [e.g. stock browser, safari] 38 | - Version [e.g. 22] 39 | 40 | **Additional context** 41 | Add any other context about the problem here. 42 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | /public/hot 3 | /public/storage 4 | /storage/*.key 5 | /vendor 6 | .env 7 | .env.backup 8 | .phpunit.result.cache 9 | Homestead.json 10 | Homestead.yaml 11 | npm-debug.log 12 | yarn-error.log 13 | public/css/app.css 14 | public/js/app.js 15 | public/js/vendor.js 16 | public/js/manifest.js 17 | public/fonts/vendor 18 | public/images/vendor 19 | public/mix-manifest.json 20 | -------------------------------------------------------------------------------- /VERSION: -------------------------------------------------------------------------------- 1 | 00000000 2 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | q* 2 | !public/ 3 | !.gitignore 4 | -------------------------------------------------------------------------------- /app/Classes/LDAP/Attribute/Binary.php: -------------------------------------------------------------------------------- 1 | with('o',$this) 22 | ->with('edit',$edit) 23 | ->with('old',$old) 24 | ->with('new',$new) 25 | ->with('updated',$updated) 26 | ->with('f',new \finfo); 27 | } 28 | } -------------------------------------------------------------------------------- /app/Classes/LDAP/Attribute/Certificate.php: -------------------------------------------------------------------------------- 1 | values_old,'binary.'.$key)),80)) 24 | ); 25 | } 26 | 27 | public function cert_info(string $index,int $key=0): mixed 28 | { 29 | if (! array_key_exists($key,$this->_object)) 30 | $this->_object[$key] = openssl_x509_parse(openssl_x509_read($this->certificate($key))); 31 | 32 | 33 | return Arr::get($this->_object[$key],$index); 34 | } 35 | 36 | public function expires($key=0): Carbon 37 | { 38 | return Carbon::createFromTimestampUTC($this->cert_info('validTo_time_t',$key)); 39 | } 40 | 41 | public function subject($key=0): string 42 | { 43 | $subject = collect($this->cert_info('subject',$key))->reverse(); 44 | 45 | return $subject->map(fn($item,$key)=>sprintf("%s=%s",$key,$item))->join(','); 46 | } 47 | } -------------------------------------------------------------------------------- /app/Classes/LDAP/Attribute/CertificateList.php: -------------------------------------------------------------------------------- 1 | with('o',$this); 20 | } 21 | } -------------------------------------------------------------------------------- /app/Classes/LDAP/Attribute/KrbPrincipalKey.php: -------------------------------------------------------------------------------- 1 | with('o',$this) 24 | ->with('edit',$edit) 25 | ->with('old',$old) 26 | ->with('new',$new) 27 | ->with('updated',$updated); 28 | } 29 | 30 | public function render_item_old(string $dotkey): ?string 31 | { 32 | return parent::render_item_old($dotkey) 33 | ? str_repeat('*',16) 34 | : NULL; 35 | } 36 | 37 | public function render_item_new(string $dotkey): ?string 38 | { 39 | return parent::render_item_new($dotkey) 40 | ? str_repeat('*',16) 41 | : NULL; 42 | } 43 | } -------------------------------------------------------------------------------- /app/Classes/LDAP/Attribute/NoAttrTags/Generic.php: -------------------------------------------------------------------------------- 1 | password($source)); 19 | } 20 | 21 | public function encode(string $password): string 22 | { 23 | return sprintf('{%s}%s',self::key,password_hash($password,PASSWORD_ARGON2I)); 24 | } 25 | } -------------------------------------------------------------------------------- /app/Classes/LDAP/Attribute/Password/Argon2id.php: -------------------------------------------------------------------------------- 1 | password($source))); 19 | } 20 | 21 | public function encode(string $password): string 22 | { 23 | return sprintf('{%s}%s',self::key,base64_encode(password_hash($password,PASSWORD_ARGON2ID))); 24 | } 25 | } -------------------------------------------------------------------------------- /app/Classes/LDAP/Attribute/Password/Base.php: -------------------------------------------------------------------------------- 1 | encode($compare); 53 | } 54 | 55 | protected function salted_hash(string $password,string $algo,int $salt_size=8,?string $salt=NULL): string 56 | { 57 | if (is_null($salt)) 58 | $salt = hex2bin(random_salt($salt_size)); 59 | 60 | return base64_encode(hash($algo,$password.$salt,true).$salt); 61 | } 62 | 63 | protected function salted_salt(string $source): string 64 | { 65 | $hash = base64_decode(substr($source,strlen(static::key)+2)); 66 | return substr($hash,strlen($hash)-static::salt/2); 67 | } 68 | } -------------------------------------------------------------------------------- /app/Classes/LDAP/Attribute/Password/Bcrypt.php: -------------------------------------------------------------------------------- 1 | 8, 11 | ]; 12 | 13 | public function compare(string $source,string $compare): bool 14 | { 15 | return password_verify($compare,base64_decode($this->password($source))); 16 | } 17 | 18 | public function encode(string $password): string 19 | { 20 | return sprintf('{%s}%s',self::key,base64_encode(password_hash($password,PASSWORD_BCRYPT,self::options))); 21 | } 22 | } -------------------------------------------------------------------------------- /app/Classes/LDAP/Attribute/Password/Blowfish.php: -------------------------------------------------------------------------------- 1 | encode($compare,$this->salted_salt($source)); 13 | } 14 | 15 | public function encode(string $password,?string $salt=NULL): string 16 | { 17 | if (is_null($salt)) 18 | $salt = hex2bin(random_salt(self::salt)); 19 | 20 | return sprintf('{%s}%s',self::key,$this->salted_hash($password,'md5',self::salt,$salt)); 21 | } 22 | } -------------------------------------------------------------------------------- /app/Classes/LDAP/Attribute/Password/SSHA.php: -------------------------------------------------------------------------------- 1 | encode($compare,$this->salted_salt($source)); 13 | } 14 | 15 | public function encode(string $password,?string $salt=NULL): string 16 | { 17 | return sprintf('{%s}%s',self::key,$this->salted_hash($password,'sha1',self::salt,$salt)); 18 | } 19 | 20 | public static function subid(string $password): bool 21 | { 22 | return preg_match('/^{'.static::key.'}/',$password); 23 | } 24 | } -------------------------------------------------------------------------------- /app/Classes/LDAP/Attribute/Password/SSHA256.php: -------------------------------------------------------------------------------- 1 | encode($compare,$this->salted_salt($source)); 13 | } 14 | 15 | public function encode(string $password,?string $salt=NULL): string 16 | { 17 | return sprintf('{%s}%s',self::key,$this->salted_hash($password,'sha256',self::salt,$salt)); 18 | } 19 | } -------------------------------------------------------------------------------- /app/Classes/LDAP/Attribute/Password/SSHA384.php: -------------------------------------------------------------------------------- 1 | encode($compare,$this->salted_salt($source)); 13 | } 14 | 15 | public function encode(string $password,?string $salt=NULL): string 16 | { 17 | return sprintf('{%s}%s',self::key,$this->salted_hash($password,'sha384',self::salt,$salt)); 18 | } 19 | } -------------------------------------------------------------------------------- /app/Classes/LDAP/Attribute/Password/SSHA512.php: -------------------------------------------------------------------------------- 1 | encode($compare,$this->salted_salt($source)); 13 | } 14 | 15 | public function encode(string $password,?string $salt=NULL): string 16 | { 17 | return sprintf('{%s}%s',self::key,$this->salted_hash($password,'sha512',self::salt,$salt)); 18 | } 19 | } -------------------------------------------------------------------------------- /app/Classes/LDAP/Attribute/RDN.php: -------------------------------------------------------------------------------- 1 | $this->base, 26 | 'attrs' => $this->attrs->pluck('name'), 27 | default => parent::__get($key), 28 | }; 29 | } 30 | 31 | public function hints(): Collection 32 | { 33 | return collect([ 34 | 'required' => __('RDN is required') 35 | ]); 36 | } 37 | 38 | public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,bool $updated=FALSE): View 39 | { 40 | return view('components.attribute.rdn') 41 | ->with('o',$this); 42 | } 43 | 44 | public function setAttributes(Collection $attrs): void 45 | { 46 | $this->attrs = $attrs; 47 | } 48 | 49 | public function setBase(string $base): void 50 | { 51 | $this->base = $base; 52 | } 53 | } -------------------------------------------------------------------------------- /app/Classes/LDAP/Attribute/Schema.php: -------------------------------------------------------------------------------- 1 | put($x=Arr::get($fields,0),[ 41 | 'title'=>Arr::get($fields,1,$x), 42 | 'ref'=>Arr::get($fields,2), 43 | 'desc'=>Arr::get($fields,3,__('No description available, can you help with one?')), 44 | ]); 45 | } 46 | 47 | fclose($f); 48 | 49 | return $result; 50 | }); 51 | 52 | return Arr::get(($array ? $array->get($string) : []), 53 | $key, 54 | __('No description available, can you help with one?')); 55 | } 56 | 57 | public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,bool $updated=FALSE): View 58 | { 59 | // @note Schema attributes cannot be edited 60 | return view('components.attribute.internal') 61 | ->with('o',$this); 62 | } 63 | } -------------------------------------------------------------------------------- /app/Classes/LDAP/Attribute/Schema/Generic.php: -------------------------------------------------------------------------------- 1 | with('o',$this); 20 | } 21 | } -------------------------------------------------------------------------------- /app/Classes/LDAP/Attribute/Schema/Mechanisms.php: -------------------------------------------------------------------------------- 1 | 21 | * "SCRAM-SHA-1" => array:3 [▼ 22 | * "title" => "Salted Challenge Response Authentication Mechanism (SCRAM) SHA1" 23 | * "ref" => "RFC 5802" 24 | * "desc" => "This specification describes a family of authentication mechanisms called the Salted Challenge Response Authentication Mechanism (SCRAM) which addresses the req ▶" 25 | * ] 26 | * 27 | * 28 | * @param string $string The SASL Mechanism (ie, "SCRAM-SHA-1") of interest. 29 | * @param string $key The title|ref|desc to return 30 | * @return string|NULL 31 | */ 32 | public static function get(string $string,string $key): ?string 33 | { 34 | return parent::_get(config_path('ldap_supported_saslmechanisms.txt'),$string,$key); 35 | } 36 | 37 | public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,bool $updated=FALSE): View 38 | { 39 | // @note Schema attributes cannot be edited 40 | return view('components.attribute.schema.mechanisms') 41 | ->with('o',$this); 42 | } 43 | } -------------------------------------------------------------------------------- /app/Classes/LDAP/Attribute/Schema/OID.php: -------------------------------------------------------------------------------- 1 | 21 | * "1.3.6.1.4.1.4203.1.5.1" => array:3 [ 22 | * [title] => All Operational Attribute 23 | * [ref] => RFC 3673 24 | * [desc] => An LDAP extension which clients may use to request the return of all operational attributes. 25 | * ] 26 | * 27 | * 28 | * @param string $string The OID number (ie, "1.3.6.1.4.1.4203.1.5.1") of the OID of interest. 29 | * @param string $key The title|ref|desc to return 30 | * @return string|null 31 | * @testedby TranslateOidTest::testRootDSE() 32 | */ 33 | public static function get(string $string,string $key): ?string 34 | { 35 | return parent::_get(config_path('ldap_supported_oids.txt'),$string,$key); 36 | } 37 | 38 | public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE,bool $updated=FALSE): View 39 | { 40 | // @note Schema attributes cannot be edited 41 | return view('components.attribute.schema.oid') 42 | ->with('o',$this); 43 | } 44 | } -------------------------------------------------------------------------------- /app/Classes/LDAP/Export.php: -------------------------------------------------------------------------------- 1 | items = $items; 28 | } 29 | 30 | abstract public function __toString(): string; 31 | 32 | protected function header() 33 | { 34 | $output = ''; 35 | 36 | $output .= sprintf('# %s %s',__(static::type.' for'),($x=$this->items->first())).$this->br; 37 | $output .= sprintf('# %s: %s (%s)', 38 | __('Server'), 39 | $x->getConnection()->getConfiguration()->get('name'), 40 | $x->getConnection()->getLdapConnection()->getHost()).$this->br; 41 | //$output .= sprintf('# %s: %s',__('Search Scope'),$this->scope).$this->br; 42 | //$output .= sprintf('# %s: %s',__('Search Filter'),$this->entry->dn).$this->br; 43 | $output .= sprintf('# %s: %s',__('Total Entries'),$this->items->count()).$this->br; 44 | $output .= '#'.$this->br; 45 | $output .= sprintf('# %s %s (%s) on %s',__('Generated by'),config('app.name'),config('app.url'),date('F j, Y g:i a')).$this->br; 46 | $output .= sprintf('# %s %s',__('Exported by'),Auth::user() ?: 'Anonymous').$this->br; 47 | $output .= sprintf('# %s: %s',__('Version'),config('app.version')).$this->br; 48 | 49 | $output .= $this->br; 50 | 51 | return $output; 52 | } 53 | } -------------------------------------------------------------------------------- /app/Classes/LDAP/Schema/ObjectClassAttribute.php: -------------------------------------------------------------------------------- 1 | name = $name; 30 | $this->source = $source; 31 | } 32 | 33 | public function __get(string $key): mixed 34 | { 35 | return match ($key) { 36 | 'source' => $this->source, 37 | default => parent::__get($key), 38 | }; 39 | } 40 | } -------------------------------------------------------------------------------- /app/Exceptions/Import/AttributeException.php: -------------------------------------------------------------------------------- 1 | term,'=')) { 20 | list($attr,$value) = explode('=',$request->term,2); 21 | $value = trim($value); 22 | 23 | $result = collect(); 24 | 25 | foreach ($so->baseDNs() as $base) { 26 | $search = (new Entry) 27 | ->in($base); 28 | 29 | $search = ($x=Str::startsWith($value,'*')) 30 | ? $search->whereEndsWith($attr,substr($value,1)) 31 | : $search->whereStartsWith($attr,$value); 32 | 33 | $result = $result->merge($search->get()); 34 | } 35 | 36 | return $result 37 | ->map(fn($item)=>[ 38 | 'name'=>$item->getDN(), 39 | 'value'=>Crypt::encryptString($item->getDN()), 40 | 'category'=>sprintf('%s: [%s=%s%s]',__('Result'),$attr,$value,($x ? '' : '*')) 41 | ]); 42 | 43 | // We are searching for an attribute 44 | } else { 45 | $attrs = $so 46 | ->schema('attributetypes') 47 | ->sortBy('name') 48 | ->filter(fn($item)=>Str::contains($item->name_lc,strtolower($request->term))); 49 | 50 | return $attrs 51 | ->map(fn($item)=>[ 52 | 'name'=>$item->name, 53 | 'value'=>'', 54 | 'category'=>__('Select attribute...') 55 | ]) 56 | ->values(); 57 | } 58 | } 59 | } -------------------------------------------------------------------------------- /app/Http/Middleware/AllowAnonymous.php: -------------------------------------------------------------------------------- 1 | path() !== 'login') 22 | && ((! Session::has('username_encrypt')) || (! Session::has('password_encrypt')))) 23 | return redirect() 24 | ->to('/login'); 25 | 26 | return $next($request); 27 | } 28 | } -------------------------------------------------------------------------------- /app/Http/Middleware/ApplicationSession.php: -------------------------------------------------------------------------------- 1 | request('POST',sprintf('%s/%s',self::UPDATE_SERVER,strtolower(config('app.version')))); 46 | 47 | if ($response->getStatusCode() === 200) { 48 | $result = json_decode($response->getBody()); 49 | 50 | Log::debug(sprintf('CU_:- Update server returned...'),['update'=>$result]); 51 | 52 | return $result; 53 | } 54 | 55 | } catch (\Exception $e) { 56 | Log::debug(sprintf('CU_:- Exception connecting to update server'),['e'=>get_class($e)]); 57 | } 58 | 59 | return NULL; 60 | }); 61 | } 62 | } -------------------------------------------------------------------------------- /app/Http/Middleware/SwapinAuthUser.php: -------------------------------------------------------------------------------- 1 | $key]); 37 | } 38 | 39 | // 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. 40 | $c = Container::getInstance() 41 | ->getConnection($key); 42 | 43 | $c->setConfiguration(config('ldap.connections.'.$key)); 44 | $c->setGuardResolver(fn()=>new Guard($c->getLdapConnection(),$c->getConfiguration())); 45 | 46 | return $next($request); 47 | } 48 | } -------------------------------------------------------------------------------- /app/Http/Middleware/ViewVariables.php: -------------------------------------------------------------------------------- 1 | share('server',Config::get('server')); 26 | view()->share('user',auth()->user() ?: new User); 27 | 28 | return $next($request); 29 | } 30 | } -------------------------------------------------------------------------------- /app/Http/Requests/EntryRequest.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | public function rules(): array 15 | { 16 | $r = request() ?: collect(); 17 | 18 | return config('server') 19 | ->schema('attributetypes') 20 | ->intersectByKeys($r->all()) 21 | ->map(fn($item)=>$item->validation($r->get('objectclass',[]))) 22 | ->filter() 23 | ->flatMap(fn($item)=>$item) 24 | ->toArray(); 25 | } 26 | } -------------------------------------------------------------------------------- /app/Http/Requests/ImportRequest.php: -------------------------------------------------------------------------------- 1 | 'nullable|extensions:ldif|required_without:text', 13 | 'text'=> 'nullable|prohibits:file|string|min:16', 14 | ]; 15 | } 16 | } -------------------------------------------------------------------------------- /app/Ldap/Guard.php: -------------------------------------------------------------------------------- 1 | put('username_encrypt',Crypt::encryptString($username)); 18 | session()->put('password_encrypt',Crypt::encryptString($password)); 19 | } 20 | 21 | return $result; 22 | } 23 | } -------------------------------------------------------------------------------- /app/Ldap/LdapUserRepository.php: -------------------------------------------------------------------------------- 1 | query()->find($credentials['dn']); 32 | 33 | // Look for a user using all our baseDNs 34 | foreach (Server::baseDNs(FALSE) as $base) { 35 | $query = $this->query()->setBaseDn($base); 36 | 37 | foreach ($credentials as $key => $value) { 38 | if (Str::contains($key, $this->bypassCredentialKeys)) { 39 | continue; 40 | } 41 | 42 | if (is_array($value) || $value instanceof Arrayable) { 43 | $query->whereIn($key, $value); 44 | } else { 45 | $query->where($key, $value); 46 | } 47 | } 48 | 49 | if (! is_null($user = $query->first())) { 50 | event(new DiscoveredWithCredentials($user)); 51 | 52 | return $user; 53 | } 54 | } 55 | 56 | return NULL; 57 | } 58 | 59 | /** 60 | * Get a user by their object GUID. 61 | * 62 | * @param string $guid 63 | * 64 | * @return Model|null 65 | * @throws \LdapRecord\Query\ObjectNotFoundException 66 | */ 67 | public function findByGuid($guid): ?Model 68 | { 69 | // Look for a user using all our baseDNs 70 | foreach (Server::baseDNs(FALSE) as $base) { 71 | $user = $this->query()->setBaseDn($base)->findByGuid($guid); 72 | 73 | if ($user) 74 | return $user; 75 | } 76 | 77 | return NULL; 78 | } 79 | } -------------------------------------------------------------------------------- /app/Ldap/Rules/LoginObjectclassRule.php: -------------------------------------------------------------------------------- 1 | objectclass ?: []), 22 | array_map('strtolower',$x) 23 | )); 24 | 25 | // Otherwise allow the user to login 26 | } else { 27 | return TRUE; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /app/Ldap/User.php: -------------------------------------------------------------------------------- 1 | exists ? parent::getDn() : 'Anonymous'; 28 | } 29 | } -------------------------------------------------------------------------------- /app/Providers/AppServiceProvider.php: -------------------------------------------------------------------------------- 1 | loadViewsFrom(__DIR__.'/../../resources/themes/architect/views/','architect'); 32 | 33 | // Enable pluck on collections to work on private values 34 | Collection::macro('ppluck', 35 | fn($attr)=>$this 36 | ->map(fn($item)=>$item->{$attr}) 37 | ->values()); 38 | } 39 | } -------------------------------------------------------------------------------- /app/Rules/DNExists.php: -------------------------------------------------------------------------------- 1 | fetch($dn)) 25 | $fail(sprintf('The DN %s doesnt exist.',$dn)); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/Rules/HasStructuralObjectClass.php: -------------------------------------------------------------------------------- 1 | dot() as $item) 24 | if ($item && config('server')->schema('objectclasses',$item)->isStructural()) 25 | return; 26 | 27 | $fail('There isnt a Structural Objectclass.'); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/Traits/MD5Updates.php: -------------------------------------------------------------------------------- 1 | values_old->dot()->keys()->merge($this->values->dot()->keys())->unique() as $dotkey) 15 | if ((Arr::get($this->values_old->dot(),$dotkey) !== Arr::get($this->values->dot(),$dotkey)) 16 | && (md5(Arr::get($this->values_old->dot(),$dotkey)) !== Arr::get($this->values->dot(),$dotkey))) 17 | return TRUE; 18 | 19 | return FALSE; 20 | } 21 | } -------------------------------------------------------------------------------- /app/View/Components/Attribute.php: -------------------------------------------------------------------------------- 1 | o = $o; 24 | $this->edit = $edit; 25 | $this->old = $old; 26 | $this->new = $new; 27 | $this->updated = $updated; 28 | } 29 | 30 | /** 31 | * Get the view / contents that represent the component. 32 | * 33 | * @return View|string 34 | */ 35 | public function render(): View|string 36 | { 37 | return $this->o 38 | ? $this->o 39 | ->render(edit: $this->edit,old: $this->old,new: $this->new,updated: $this->updated) 40 | : __('Unknown'); 41 | } 42 | } -------------------------------------------------------------------------------- /app/helpers.php: -------------------------------------------------------------------------------- 1 | handleCommand(new ArgvInput); 14 | 15 | exit($status); 16 | -------------------------------------------------------------------------------- /bootstrap/app.php: -------------------------------------------------------------------------------- 1 | withRouting( 11 | web: __DIR__.'/../routes/web.php', 12 | commands: __DIR__.'/../routes/console.php', 13 | health: '/up', 14 | ) 15 | ->withMiddleware(function (Middleware $middleware) { 16 | $middleware->appendToGroup( 17 | group: 'web', 18 | middleware: [ 19 | ApplicationSession::class, 20 | AllowAnonymous::class, 21 | SwapinAuthUser::class, 22 | ViewVariables::class, 23 | CheckUpdate::class, 24 | ]); 25 | 26 | $middleware->trustProxies(at: [ 27 | '10.0.0.0/8', 28 | '127.0.0.0/8', 29 | '172.16.0.0/12', 30 | '192.168.0.0/12', 31 | ]); 32 | }) 33 | ->withExceptions(function (Exceptions $exceptions) { 34 | // 35 | })->create(); -------------------------------------------------------------------------------- /bootstrap/cache/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /bootstrap/providers.php: -------------------------------------------------------------------------------- 1 | > /etc/openldap/ldap.conf 30 | 31 | # Add composer 32 | RUN curl -4 https://getcomposer.org/installer|php -- --install-dir=/usr/local/bin --filename=composer 33 | ENV COMPOSER_HOME=/var/cache/composer 34 | 35 | ENV SITE_USER=www-data 36 | 37 | # Startup for ${SITE_USER} 38 | COPY docker/init-docker /sbin/init-docker 39 | RUN chmod 550 /sbin/init-docker && chown ${SITE_USER}:0 /sbin/init-docker && chown -R ${SITE_USER}:0 ${XDG_DATA_HOME} ${XDG_CONFIG_HOME} 40 | 41 | COPY . /app 42 | 43 | RUN mkdir -p ${COMPOSER_HOME} \ 44 | && ([ -r auth.json ] && mv auth.json ${COMPOSER_HOME}) || true \ 45 | && touch .composer.refresh \ 46 | && mv .env.example .env \ 47 | && FORCE_PERMS=1 BUILD=1 /sbin/init-docker \ 48 | && rm -rf ${COMPOSER_HOME}/* composer.lock 49 | 50 | WORKDIR /app 51 | USER ${SITE_USER} 52 | 53 | # Control which port to open 54 | ENV SERVER_NAME=:8080 55 | EXPOSE 8080 56 | 57 | ENTRYPOINT [ "/sbin/init-docker" ] 58 | CMD [ "--config","/etc/caddy/Caddyfile","--adapter","caddyfile" ] 59 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "dev": "npm run development", 4 | "development": "mix", 5 | "watch": "mix watch", 6 | "watch-poll": "mix watch -- --watch-options-poll=1000", 7 | "hot": "mix watch --hot", 8 | "prod": "npm run production", 9 | "production": "mix --production" 10 | }, 11 | "resolutions": {}, 12 | "dependencies": { 13 | "@fortawesome/fontawesome-free": "^6.3.0", 14 | "@popperjs/core": "^2.11.6", 15 | "animate-sass": "^0.8.2", 16 | "axios": "^1.3.4", 17 | "bootstrap": "^5.2.3", 18 | "bootstrap-icons": "^1.11.3", 19 | "jquery": "^3.6.3", 20 | "jquery-ui": "^1.13.2", 21 | "jquery.fancytree": "^2.38.3", 22 | "laravel-mix": "^6.0.49", 23 | "less-loader": "^11.1.0", 24 | "metismenu": "^3.0.7", 25 | "pe7-icon": "^1.0.4", 26 | "resolve-url-loader": "^5.0.0", 27 | "sass": "^1.58.3", 28 | "sass-loader": "^13.2.0", 29 | "select2": "^4.1.0-rc.0", 30 | "select2-bootstrap-5-theme": "^1.3.0" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | tests/Unit 10 | 11 | 12 | tests/Feature 13 | 14 | 15 | 16 | 17 | app 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /public/.htaccess: -------------------------------------------------------------------------------- 1 | 2 | 3 | Options -MultiViews -Indexes 4 | 5 | 6 | RewriteEngine On 7 | 8 | # Handle Authorization Header 9 | RewriteCond %{HTTP:Authorization} . 10 | RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] 11 | 12 | # Redirect Trailing Slashes If Not A Folder... 13 | RewriteCond %{REQUEST_FILENAME} !-d 14 | RewriteCond %{REQUEST_URI} (.+)/$ 15 | RewriteRule ^ %1 [L,R=301] 16 | 17 | # Send Requests To Front Controller... 18 | RewriteCond %{REQUEST_FILENAME} !-d 19 | RewriteCond %{REQUEST_FILENAME} !-f 20 | RewriteRule ^ index.php [L] 21 | 22 | -------------------------------------------------------------------------------- /public/VERSION: -------------------------------------------------------------------------------- 1 | v2.2.0-dev 2 | -------------------------------------------------------------------------------- /public/css/flags/flags16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leenooks/phpLDAPadmin/b08de519d4091fe5f89192b6e7fa145f2167ae6a/public/css/flags/flags16.png -------------------------------------------------------------------------------- /public/css/flags/flags32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leenooks/phpLDAPadmin/b08de519d4091fe5f89192b6e7fa145f2167ae6a/public/css/flags/flags32.png -------------------------------------------------------------------------------- /public/css/print.css: -------------------------------------------------------------------------------- 1 | @media print { 2 | body { 3 | color: #333; 4 | font-weight: 400; 5 | font-size: 0.85em; 6 | } 7 | 8 | label { 9 | font-weight: bold; 10 | } 11 | 12 | tr { page-break-inside:avoid; } 13 | thead { display:table-header-group; } 14 | tfoot { display:table-footer-group; } 15 | 16 | .table-responsive { 17 | overflow: visible !important; 18 | } 19 | } -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leenooks/phpLDAPadmin/b08de519d4091fe5f89192b6e7fa145f2167ae6a/public/favicon.ico -------------------------------------------------------------------------------- /public/images/logo-h-lg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leenooks/phpLDAPadmin/b08de519d4091fe5f89192b6e7fa145f2167ae6a/public/images/logo-h-lg.png -------------------------------------------------------------------------------- /public/images/logo-h.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leenooks/phpLDAPadmin/b08de519d4091fe5f89192b6e7fa145f2167ae6a/public/images/logo-h.png -------------------------------------------------------------------------------- /public/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leenooks/phpLDAPadmin/b08de519d4091fe5f89192b6e7fa145f2167ae6a/public/images/logo.png -------------------------------------------------------------------------------- /public/index.php: -------------------------------------------------------------------------------- 1 | handleRequest(Request::capture()); 18 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: 3 | -------------------------------------------------------------------------------- /resources/images/user-secret-solid.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /resources/js/app.js: -------------------------------------------------------------------------------- 1 | import './bootstrap'; 2 | 3 | // Imports 4 | window.$ = window.jQuery = require('jquery'); 5 | //const $ = require('jquery'); 6 | 7 | // Fancy Tree 8 | import {createTree} from 'jquery.fancytree'; 9 | import 'jquery.fancytree/dist/modules/jquery.fancytree.edit'; 10 | import 'jquery.fancytree/dist/modules/jquery.fancytree.filter'; 11 | import 'jquery.fancytree/dist/modules/jquery.fancytree.glyph'; 12 | import 'jquery.fancytree/dist/modules/jquery.fancytree.persist'; 13 | // import 'jquery-ui/dist/jquery-ui'; // USED? 14 | import 'jquery.fancytree/dist/skin-xp/ui.fancytree.css'; 15 | 16 | // Bootstrap - included in architectui 17 | // import 'bootstrap/dist/js/bootstrap.bundle'; 18 | 19 | // Select2 20 | import 'select2/dist/js/select2'; 21 | 22 | // Architect UI 23 | import '../themes/architect/src/app'; 24 | -------------------------------------------------------------------------------- /resources/js/bootstrap.js: -------------------------------------------------------------------------------- 1 | window._ = require('lodash'); 2 | 3 | /** 4 | * We'll load the axios HTTP library which allows us to easily issue requests 5 | * to our Laravel back-end. This library automatically handles sending the 6 | * CSRF token as a header based on the value of the "XSRF" token cookie. 7 | */ 8 | 9 | window.axios = require('axios'); 10 | 11 | window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'; 12 | 13 | /** 14 | * Echo exposes an expressive API for subscribing to channels and listening 15 | * for events that are broadcast by Laravel. Echo and event broadcasting 16 | * allows your team to easily build robust real-time web applications. 17 | */ 18 | 19 | // import Echo from 'laravel-echo'; 20 | 21 | // window.Pusher = require('pusher-js'); 22 | 23 | // window.Echo = new Echo({ 24 | // broadcaster: 'pusher', 25 | // key: process.env.MIX_PUSHER_APP_KEY, 26 | // cluster: process.env.MIX_PUSHER_APP_CLUSTER, 27 | // forceTLS: true 28 | // }); 29 | -------------------------------------------------------------------------------- /resources/lang/README.md: -------------------------------------------------------------------------------- 1 | This directory contains language translation files for PLA. 2 | 3 | Language files named by 2 letter iso language name (suffixed with .json) 4 | represent the translations for that language. 5 | 6 | eg: en.json 7 | -------------------------------------------------------------------------------- /resources/lang/dev.json: -------------------------------------------------------------------------------- 1 | { 2 | "Email": "DEV:Email", 3 | "Home": "DEV:Home", 4 | "Password": "DEV:Password", 5 | "Please enter your email": "DEV:Please enter your email", 6 | "Please enter your password": "DEV:Please enter your password", 7 | "Server Info": "DEV:Server Info", 8 | "Server Name": "DEV:Server Name", 9 | "Sign in to :server": "DEV:Sign in to :server" 10 | } 11 | -------------------------------------------------------------------------------- /resources/lang/en/auth.php: -------------------------------------------------------------------------------- 1 | 'These credentials do not match our records.', 17 | 'throttle' => 'Too many login attempts. Please try again in :seconds seconds.', 18 | 19 | ]; 20 | -------------------------------------------------------------------------------- /resources/lang/en/pagination.php: -------------------------------------------------------------------------------- 1 | '« Previous', 17 | 'next' => 'Next »', 18 | 19 | ]; 20 | -------------------------------------------------------------------------------- /resources/lang/en/passwords.php: -------------------------------------------------------------------------------- 1 | 'Your password has been reset!', 17 | 'sent' => 'We have emailed your password reset link!', 18 | 'throttled' => 'Please wait before retrying.', 19 | 'token' => 'This password reset token is invalid.', 20 | 'user' => "We can't find a user with that email address.", 21 | 22 | ]; 23 | -------------------------------------------------------------------------------- /resources/sass/_variables.scss: -------------------------------------------------------------------------------- 1 | 2 | // Body 3 | $body-bg: #f8fafc; 4 | 5 | // Typography 6 | $font-family-sans-serif: "Nunito", sans-serif; 7 | $font-size-base: 0.9rem; 8 | $line-height-base: 1.6; 9 | 10 | // Colors 11 | $blue: #3490dc; 12 | $indigo: #6574cd; 13 | $purple: #9561e2; 14 | $pink: #f66D9b; 15 | $red: #e3342f; 16 | $orange: #f6993f; 17 | $yellow: #ffed4a; 18 | $green: #38c172; 19 | $teal: #4dc0b5; 20 | $cyan: #6cb2eb; 21 | -------------------------------------------------------------------------------- /resources/sass/app.scss: -------------------------------------------------------------------------------- 1 | // Architect UI 2 | @import "resources/themes/architect/src/base.scss"; 3 | 4 | // Fancy Tree 5 | @import "jquery.fancytree/dist/skin-xp/ui.fancytree"; 6 | 7 | // Select2 8 | @import "select2/dist/css/select2"; 9 | @import "select2-bootstrap-5-theme/dist/select2-bootstrap-5-theme"; 10 | 11 | // Bootstrap icons 12 | @import "bootstrap-icons" 13 | -------------------------------------------------------------------------------- /resources/themes/architect/src/components/bootstrap5/_badge.scss: -------------------------------------------------------------------------------- 1 | // Base class 2 | // 3 | // Requires one of the contextual, color modifier classes for `color` and 4 | // `background-color`. 5 | 6 | .badge { 7 | // scss-docs-start badge-css-vars 8 | --#{$prefix}badge-padding-x: #{$badge-padding-x}; 9 | --#{$prefix}badge-padding-y: #{$badge-padding-y}; 10 | @include rfs($badge-font-size, --#{$prefix}badge-font-size); 11 | --#{$prefix}badge-font-weight: #{$badge-font-weight}; 12 | --#{$prefix}badge-color: #{$badge-color}; 13 | --#{$prefix}badge-border-radius: #{$badge-border-radius}; 14 | // scss-docs-end badge-css-vars 15 | 16 | display: inline-block; 17 | padding: var(--#{$prefix}badge-padding-y) var(--#{$prefix}badge-padding-x); 18 | @include font-size(var(--#{$prefix}badge-font-size)); 19 | font-weight: var(--#{$prefix}badge-font-weight); 20 | line-height: 1; 21 | color: var(--#{$prefix}badge-color); 22 | text-align: center; 23 | white-space: nowrap; 24 | vertical-align: baseline; 25 | @include border-radius(var(--#{$prefix}badge-border-radius)); 26 | @include gradient-bg(); 27 | 28 | // Empty badges collapse automatically 29 | &:empty { 30 | display: none; 31 | } 32 | } 33 | 34 | // Quick fix for badges in buttons 35 | .btn .badge { 36 | position: relative; 37 | top: -1px; 38 | } 39 | -------------------------------------------------------------------------------- /resources/themes/architect/src/components/bootstrap5/_breadcrumb.scss: -------------------------------------------------------------------------------- 1 | .breadcrumb { 2 | // scss-docs-start breadcrumb-css-vars 3 | --#{$prefix}breadcrumb-padding-x: #{$breadcrumb-padding-x}; 4 | --#{$prefix}breadcrumb-padding-y: #{$breadcrumb-padding-y}; 5 | --#{$prefix}breadcrumb-margin-bottom: #{$breadcrumb-margin-bottom}; 6 | @include rfs($breadcrumb-font-size, --#{$prefix}breadcrumb-font-size); 7 | --#{$prefix}breadcrumb-bg: #{$breadcrumb-bg}; 8 | --#{$prefix}breadcrumb-border-radius: #{$breadcrumb-border-radius}; 9 | --#{$prefix}breadcrumb-divider-color: #{$breadcrumb-divider-color}; 10 | --#{$prefix}breadcrumb-item-padding-x: #{$breadcrumb-item-padding-x}; 11 | --#{$prefix}breadcrumb-item-active-color: #{$breadcrumb-active-color}; 12 | // scss-docs-end breadcrumb-css-vars 13 | 14 | display: flex; 15 | flex-wrap: wrap; 16 | padding: var(--#{$prefix}breadcrumb-padding-y) var(--#{$prefix}breadcrumb-padding-x); 17 | margin-bottom: var(--#{$prefix}breadcrumb-margin-bottom); 18 | @include font-size(var(--#{$prefix}breadcrumb-font-size)); 19 | list-style: none; 20 | background-color: var(--#{$prefix}breadcrumb-bg); 21 | @include border-radius(var(--#{$prefix}breadcrumb-border-radius)); 22 | } 23 | 24 | .breadcrumb-item { 25 | // The separator between breadcrumbs (by default, a forward-slash: "/") 26 | + .breadcrumb-item { 27 | padding-left: var(--#{$prefix}breadcrumb-item-padding-x); 28 | 29 | &::before { 30 | float: left; // Suppress inline spacings and underlining of the separator 31 | padding-right: var(--#{$prefix}breadcrumb-item-padding-x); 32 | color: var(--#{$prefix}breadcrumb-divider-color); 33 | content: var(--#{$prefix}breadcrumb-divider, escape-svg($breadcrumb-divider)) #{"/* rtl:"} var(--#{$prefix}breadcrumb-divider, escape-svg($breadcrumb-divider-flipped)) #{"*/"}; 34 | } 35 | } 36 | 37 | &.active { 38 | color: var(--#{$prefix}breadcrumb-item-active-color); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /resources/themes/architect/src/components/bootstrap5/_containers.scss: -------------------------------------------------------------------------------- 1 | // Container widths 2 | // 3 | // Set the container width, and override it for fixed navbars in media queries. 4 | 5 | @if $enable-container-classes { 6 | // Single container class with breakpoint max-widths 7 | .container, 8 | // 100% wide container at all breakpoints 9 | .container-fluid { 10 | @include make-container(); 11 | } 12 | 13 | // Responsive containers that are 100% wide until a breakpoint 14 | @each $breakpoint, $container-max-width in $container-max-widths { 15 | .container-#{$breakpoint} { 16 | @extend .container-fluid; 17 | } 18 | 19 | @include media-breakpoint-up($breakpoint, $grid-breakpoints) { 20 | %responsive-container-#{$breakpoint} { 21 | max-width: $container-max-width; 22 | } 23 | 24 | // Extend each breakpoint which is smaller or equal to the current breakpoint 25 | $extend-breakpoint: true; 26 | 27 | @each $name, $width in $grid-breakpoints { 28 | @if ($extend-breakpoint) { 29 | .container#{breakpoint-infix($name, $grid-breakpoints)} { 30 | @extend %responsive-container-#{$breakpoint}; 31 | } 32 | 33 | // Once the current breakpoint is reached, stop extending 34 | @if ($breakpoint == $name) { 35 | $extend-breakpoint: false; 36 | } 37 | } 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /resources/themes/architect/src/components/bootstrap5/_forms.scss: -------------------------------------------------------------------------------- 1 | @import "forms/labels"; 2 | @import "forms/form-text"; 3 | @import "forms/form-control"; 4 | @import "forms/form-select"; 5 | @import "forms/form-check"; 6 | @import "forms/form-range"; 7 | @import "forms/floating-labels"; 8 | @import "forms/input-group"; 9 | @import "forms/validation"; 10 | -------------------------------------------------------------------------------- /resources/themes/architect/src/components/bootstrap5/_grid.scss: -------------------------------------------------------------------------------- 1 | // Row 2 | // 3 | // Rows contain your columns. 4 | 5 | :root { 6 | @each $name, $value in $grid-breakpoints { 7 | --#{$prefix}breakpoint-#{$name}: #{$value}; 8 | } 9 | } 10 | 11 | @if $enable-grid-classes { 12 | .row { 13 | @include make-row(); 14 | 15 | > * { 16 | @include make-col-ready(); 17 | } 18 | } 19 | } 20 | 21 | @if $enable-cssgrid { 22 | .grid { 23 | display: grid; 24 | grid-template-rows: repeat(var(--#{$prefix}rows, 1), 1fr); 25 | grid-template-columns: repeat(var(--#{$prefix}columns, #{$grid-columns}), 1fr); 26 | gap: var(--#{$prefix}gap, #{$grid-gutter-width}); 27 | 28 | @include make-cssgrid(); 29 | } 30 | } 31 | 32 | 33 | // Columns 34 | // 35 | // Common styles for small and large grid columns 36 | 37 | @if $enable-grid-classes { 38 | @include make-grid-columns(); 39 | } 40 | -------------------------------------------------------------------------------- /resources/themes/architect/src/components/bootstrap5/_helpers.scss: -------------------------------------------------------------------------------- 1 | @import "helpers/clearfix"; 2 | @import "helpers/color-bg"; 3 | @import "helpers/colored-links"; 4 | @import "helpers/focus-ring"; 5 | @import "helpers/icon-link"; 6 | @import "helpers/ratio"; 7 | @import "helpers/position"; 8 | @import "helpers/stacks"; 9 | @import "helpers/visually-hidden"; 10 | @import "helpers/stretched-link"; 11 | @import "helpers/text-truncation"; 12 | @import "helpers/vr"; 13 | -------------------------------------------------------------------------------- /resources/themes/architect/src/components/bootstrap5/_images.scss: -------------------------------------------------------------------------------- 1 | // Responsive images (ensure images don't scale beyond their parents) 2 | // 3 | // This is purposefully opt-in via an explicit class rather than being the default for all ``s. 4 | // We previously tried the "images are responsive by default" approach in Bootstrap v2, 5 | // and abandoned it in Bootstrap v3 because it breaks lots of third-party widgets (including Google Maps) 6 | // which weren't expecting the images within themselves to be involuntarily resized. 7 | // See also https://github.com/twbs/bootstrap/issues/18178 8 | .img-fluid { 9 | @include img-fluid(); 10 | } 11 | 12 | 13 | // Image thumbnails 14 | .img-thumbnail { 15 | padding: $thumbnail-padding; 16 | background-color: $thumbnail-bg; 17 | border: $thumbnail-border-width solid $thumbnail-border-color; 18 | @include border-radius($thumbnail-border-radius); 19 | @include box-shadow($thumbnail-box-shadow); 20 | 21 | // Keep them at most 100% wide 22 | @include img-fluid(); 23 | } 24 | 25 | // 26 | // Figures 27 | // 28 | 29 | .figure { 30 | // Ensures the caption's text aligns with the image. 31 | display: inline-block; 32 | } 33 | 34 | .figure-img { 35 | margin-bottom: $spacer * .5; 36 | line-height: 1; 37 | } 38 | 39 | .figure-caption { 40 | @include font-size($figure-caption-font-size); 41 | color: $figure-caption-color; 42 | } 43 | -------------------------------------------------------------------------------- /resources/themes/architect/src/components/bootstrap5/_mixins.scss: -------------------------------------------------------------------------------- 1 | // Toggles 2 | // 3 | // Used in conjunction with global variables to enable certain theme features. 4 | 5 | // Vendor 6 | @import "vendor/rfs"; 7 | 8 | // Deprecate 9 | @import "mixins/deprecate"; 10 | 11 | // Helpers 12 | @import "mixins/breakpoints"; 13 | @import "mixins/color-mode"; 14 | @import "mixins/color-scheme"; 15 | @import "mixins/image"; 16 | @import "mixins/resize"; 17 | @import "mixins/visually-hidden"; 18 | @import "mixins/reset-text"; 19 | @import "mixins/text-truncate"; 20 | 21 | // Utilities 22 | @import "mixins/utilities"; 23 | 24 | // Components 25 | @import "mixins/backdrop"; 26 | @import "mixins/buttons"; 27 | @import "mixins/caret"; 28 | @import "mixins/pagination"; 29 | @import "mixins/lists"; 30 | @import "mixins/forms"; 31 | @import "mixins/table-variants"; 32 | 33 | // Skins 34 | @import "mixins/border-radius"; 35 | @import "mixins/box-shadow"; 36 | @import "mixins/gradients"; 37 | @import "mixins/transition"; 38 | 39 | // Layout 40 | @import "mixins/clearfix"; 41 | @import "mixins/container"; 42 | @import "mixins/grid"; 43 | -------------------------------------------------------------------------------- /resources/themes/architect/src/components/bootstrap5/_transitions.scss: -------------------------------------------------------------------------------- 1 | .fade { 2 | @include transition($transition-fade); 3 | 4 | &:not(.show) { 5 | opacity: 0; 6 | } 7 | } 8 | 9 | // scss-docs-start collapse-classes 10 | .collapse { 11 | &:not(.show) { 12 | display: none; 13 | } 14 | } 15 | 16 | .collapsing { 17 | height: 0; 18 | overflow: hidden; 19 | @include transition($transition-collapse); 20 | 21 | &.collapse-horizontal { 22 | width: 0; 23 | height: auto; 24 | @include transition($transition-collapse-width); 25 | } 26 | } 27 | // scss-docs-end collapse-classes 28 | -------------------------------------------------------------------------------- /resources/themes/architect/src/components/bootstrap5/_type.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Headings 3 | // 4 | .h1 { 5 | @extend h1; 6 | } 7 | 8 | .h2 { 9 | @extend h2; 10 | } 11 | 12 | .h3 { 13 | @extend h3; 14 | } 15 | 16 | .h4 { 17 | @extend h4; 18 | } 19 | 20 | .h5 { 21 | @extend h5; 22 | } 23 | 24 | .h6 { 25 | @extend h6; 26 | } 27 | 28 | 29 | .lead { 30 | @include font-size($lead-font-size); 31 | font-weight: $lead-font-weight; 32 | } 33 | 34 | // Type display classes 35 | @each $display, $font-size in $display-font-sizes { 36 | .display-#{$display} { 37 | @include font-size($font-size); 38 | font-family: $display-font-family; 39 | font-style: $display-font-style; 40 | font-weight: $display-font-weight; 41 | line-height: $display-line-height; 42 | } 43 | } 44 | 45 | // 46 | // Emphasis 47 | // 48 | .small { 49 | @extend small; 50 | } 51 | 52 | .mark { 53 | @extend mark; 54 | } 55 | 56 | // 57 | // Lists 58 | // 59 | 60 | .list-unstyled { 61 | @include list-unstyled(); 62 | } 63 | 64 | // Inline turns list items into inline-block 65 | .list-inline { 66 | @include list-unstyled(); 67 | } 68 | .list-inline-item { 69 | display: inline-block; 70 | 71 | &:not(:last-child) { 72 | margin-right: $list-inline-padding; 73 | } 74 | } 75 | 76 | 77 | // 78 | // Misc 79 | // 80 | 81 | // Builds on `abbr` 82 | .initialism { 83 | @include font-size($initialism-font-size); 84 | text-transform: uppercase; 85 | } 86 | 87 | // Blockquotes 88 | .blockquote { 89 | margin-bottom: $blockquote-margin-y; 90 | @include font-size($blockquote-font-size); 91 | 92 | > :last-child { 93 | margin-bottom: 0; 94 | } 95 | } 96 | 97 | .blockquote-footer { 98 | margin-top: -$blockquote-margin-y; 99 | margin-bottom: $blockquote-margin-y; 100 | @include font-size($blockquote-footer-font-size); 101 | color: $blockquote-footer-color; 102 | 103 | &::before { 104 | content: "\2014\00A0"; // em dash, nbsp 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /resources/themes/architect/src/components/bootstrap5/bootstrap-grid.scss: -------------------------------------------------------------------------------- 1 | @import "mixins/banner"; 2 | @include bsBanner(Grid); 3 | 4 | $include-column-box-sizing: true !default; 5 | 6 | @import "functions"; 7 | @import "variables"; 8 | @import "variables-dark"; 9 | @import "maps"; 10 | 11 | @import "mixins/breakpoints"; 12 | @import "mixins/container"; 13 | @import "mixins/grid"; 14 | @import "mixins/utilities"; 15 | 16 | @import "vendor/rfs"; 17 | 18 | @import "containers"; 19 | @import "grid"; 20 | 21 | @import "utilities"; 22 | // Only use the utilities we need 23 | // stylelint-disable-next-line scss/dollar-variable-default 24 | $utilities: map-get-multiple( 25 | $utilities, 26 | ( 27 | "display", 28 | "order", 29 | "flex", 30 | "flex-direction", 31 | "flex-grow", 32 | "flex-shrink", 33 | "flex-wrap", 34 | "justify-content", 35 | "align-items", 36 | "align-content", 37 | "align-self", 38 | "margin", 39 | "margin-x", 40 | "margin-y", 41 | "margin-top", 42 | "margin-end", 43 | "margin-bottom", 44 | "margin-start", 45 | "negative-margin", 46 | "negative-margin-x", 47 | "negative-margin-y", 48 | "negative-margin-top", 49 | "negative-margin-end", 50 | "negative-margin-bottom", 51 | "negative-margin-start", 52 | "padding", 53 | "padding-x", 54 | "padding-y", 55 | "padding-top", 56 | "padding-end", 57 | "padding-bottom", 58 | "padding-start", 59 | ) 60 | ); 61 | 62 | @import "utilities/api"; 63 | -------------------------------------------------------------------------------- /resources/themes/architect/src/components/bootstrap5/bootstrap-reboot.scss: -------------------------------------------------------------------------------- 1 | @import "mixins/banner"; 2 | @include bsBanner(Reboot); 3 | 4 | @import "functions"; 5 | @import "variables"; 6 | @import "variables-dark"; 7 | @import "maps"; 8 | @import "mixins"; 9 | @import "root"; 10 | @import "reboot"; 11 | -------------------------------------------------------------------------------- /resources/themes/architect/src/components/bootstrap5/bootstrap-utilities.scss: -------------------------------------------------------------------------------- 1 | @import "mixins/banner"; 2 | @include bsBanner(Utilities); 3 | 4 | // Configuration 5 | @import "functions"; 6 | @import "variables"; 7 | @import "variables-dark"; 8 | @import "maps"; 9 | @import "mixins"; 10 | @import "utilities"; 11 | 12 | // Layout & components 13 | @import "root"; 14 | 15 | // Helpers 16 | @import "helpers"; 17 | 18 | // Utilities 19 | @import "utilities/api"; 20 | -------------------------------------------------------------------------------- /resources/themes/architect/src/components/bootstrap5/bootstrap.scss: -------------------------------------------------------------------------------- 1 | @import "mixins/banner"; 2 | @include bsBanner(""); 3 | 4 | 5 | // scss-docs-start import-stack 6 | // Configuration 7 | @import "functions"; 8 | @import "variables"; 9 | @import "variables-dark"; 10 | @import "maps"; 11 | @import "mixins"; 12 | @import "utilities"; 13 | 14 | // Layout & components 15 | @import "root"; 16 | @import "reboot"; 17 | @import "type"; 18 | @import "images"; 19 | @import "containers"; 20 | @import "grid"; 21 | @import "tables"; 22 | @import "forms"; 23 | @import "buttons"; 24 | @import "transitions"; 25 | @import "dropdown"; 26 | @import "button-group"; 27 | @import "nav"; 28 | @import "navbar"; 29 | @import "card"; 30 | @import "accordion"; 31 | @import "breadcrumb"; 32 | @import "pagination"; 33 | @import "badge"; 34 | @import "alert"; 35 | @import "progress"; 36 | @import "list-group"; 37 | @import "close"; 38 | @import "toasts"; 39 | @import "modal"; 40 | @import "tooltip"; 41 | @import "popover"; 42 | @import "carousel"; 43 | @import "spinners"; 44 | @import "offcanvas"; 45 | @import "placeholders"; 46 | 47 | // Helpers 48 | @import "helpers"; 49 | 50 | // Utilities 51 | @import "utilities/api"; 52 | // scss-docs-end import-stack 53 | -------------------------------------------------------------------------------- /resources/themes/architect/src/components/bootstrap5/forms/_form-text.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Form text 3 | // 4 | 5 | .form-text { 6 | margin-top: $form-text-margin-top; 7 | @include font-size($form-text-font-size); 8 | font-style: $form-text-font-style; 9 | font-weight: $form-text-font-weight; 10 | color: $form-text-color; 11 | } 12 | -------------------------------------------------------------------------------- /resources/themes/architect/src/components/bootstrap5/forms/_labels.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Labels 3 | // 4 | 5 | .form-label { 6 | margin-bottom: $form-label-margin-bottom; 7 | @include font-size($form-label-font-size); 8 | font-style: $form-label-font-style; 9 | font-weight: $form-label-font-weight; 10 | color: $form-label-color; 11 | } 12 | 13 | // For use with horizontal and inline forms, when you need the label (or legend) 14 | // text to align with the form controls. 15 | .col-form-label { 16 | padding-top: add($input-padding-y, $input-border-width); 17 | padding-bottom: add($input-padding-y, $input-border-width); 18 | margin-bottom: 0; // Override the `` default 19 | @include font-size(inherit); // Override the `` default 20 | font-style: $form-label-font-style; 21 | font-weight: $form-label-font-weight; 22 | line-height: $input-line-height; 23 | color: $form-label-color; 24 | } 25 | 26 | .col-form-label-lg { 27 | padding-top: add($input-padding-y-lg, $input-border-width); 28 | padding-bottom: add($input-padding-y-lg, $input-border-width); 29 | @include font-size($input-font-size-lg); 30 | } 31 | 32 | .col-form-label-sm { 33 | padding-top: add($input-padding-y-sm, $input-border-width); 34 | padding-bottom: add($input-padding-y-sm, $input-border-width); 35 | @include font-size($input-font-size-sm); 36 | } 37 | -------------------------------------------------------------------------------- /resources/themes/architect/src/components/bootstrap5/forms/_validation.scss: -------------------------------------------------------------------------------- 1 | // Form validation 2 | // 3 | // Provide feedback to users when form field values are valid or invalid. Works 4 | // primarily for client-side validation via scoped `:invalid` and `:valid` 5 | // pseudo-classes but also includes `.is-invalid` and `.is-valid` classes for 6 | // server-side validation. 7 | 8 | // scss-docs-start form-validation-states-loop 9 | @each $state, $data in $form-validation-states { 10 | @include form-validation-state($state, $data...); 11 | } 12 | // scss-docs-end form-validation-states-loop 13 | -------------------------------------------------------------------------------- /resources/themes/architect/src/components/bootstrap5/helpers/_clearfix.scss: -------------------------------------------------------------------------------- 1 | .clearfix { 2 | @include clearfix(); 3 | } 4 | -------------------------------------------------------------------------------- /resources/themes/architect/src/components/bootstrap5/helpers/_color-bg.scss: -------------------------------------------------------------------------------- 1 | // All-caps `RGBA()` function used because of this Sass bug: https://github.com/sass/node-sass/issues/2251 2 | @each $color, $value in $theme-colors { 3 | .text-bg-#{$color} { 4 | color: color-contrast($value) if($enable-important-utilities, !important, null); 5 | background-color: RGBA(var(--#{$prefix}#{$color}-rgb), var(--#{$prefix}bg-opacity, 1)) if($enable-important-utilities, !important, null); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /resources/themes/architect/src/components/bootstrap5/helpers/_colored-links.scss: -------------------------------------------------------------------------------- 1 | // All-caps `RGBA()` function used because of this Sass bug: https://github.com/sass/node-sass/issues/2251 2 | @each $color, $value in $theme-colors { 3 | .link-#{$color} { 4 | color: RGBA(var(--#{$prefix}#{$color}-rgb), var(--#{$prefix}link-opacity, 1)) if($enable-important-utilities, !important, null); 5 | text-decoration-color: RGBA(var(--#{$prefix}#{$color}-rgb), var(--#{$prefix}link-underline-opacity, 1)) if($enable-important-utilities, !important, null); 6 | 7 | @if $link-shade-percentage != 0 { 8 | &:hover, 9 | &:focus { 10 | $hover-color: if(color-contrast($value) == $color-contrast-light, shade-color($value, $link-shade-percentage), tint-color($value, $link-shade-percentage)); 11 | color: RGBA(#{to-rgb($hover-color)}, var(--#{$prefix}link-opacity, 1)) if($enable-important-utilities, !important, null); 12 | text-decoration-color: RGBA(to-rgb($hover-color), var(--#{$prefix}link-underline-opacity, 1)) if($enable-important-utilities, !important, null); 13 | } 14 | } 15 | } 16 | } 17 | 18 | // One-off special link helper as a bridge until v6 19 | .link-body-emphasis { 20 | color: RGBA(var(--#{$prefix}emphasis-color-rgb), var(--#{$prefix}link-opacity, 1)) if($enable-important-utilities, !important, null); 21 | text-decoration-color: RGBA(var(--#{$prefix}emphasis-color-rgb), var(--#{$prefix}link-underline-opacity, 1)) if($enable-important-utilities, !important, null); 22 | 23 | @if $link-shade-percentage != 0 { 24 | &:hover, 25 | &:focus { 26 | color: RGBA(var(--#{$prefix}emphasis-color-rgb), var(--#{$prefix}link-opacity, .75)) if($enable-important-utilities, !important, null); 27 | text-decoration-color: RGBA(var(--#{$prefix}emphasis-color-rgb), var(--#{$prefix}link-underline-opacity, .75)) if($enable-important-utilities, !important, null); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /resources/themes/architect/src/components/bootstrap5/helpers/_focus-ring.scss: -------------------------------------------------------------------------------- 1 | .focus-ring:focus { 2 | outline: 0; 3 | // By default, there is no `--bs-focus-ring-x`, `--bs-focus-ring-y`, or `--bs-focus-ring-blur`, but we provide CSS variables with fallbacks to initial `0` values 4 | box-shadow: var(--#{$prefix}focus-ring-x, 0) var(--#{$prefix}focus-ring-y, 0) var(--#{$prefix}focus-ring-blur, 0) var(--#{$prefix}focus-ring-width) var(--#{$prefix}focus-ring-color); 5 | } 6 | -------------------------------------------------------------------------------- /resources/themes/architect/src/components/bootstrap5/helpers/_icon-link.scss: -------------------------------------------------------------------------------- 1 | .icon-link { 2 | display: inline-flex; 3 | gap: $icon-link-gap; 4 | align-items: center; 5 | text-decoration-color: rgba(var(--#{$prefix}link-color-rgb), var(--#{$prefix}link-opacity, .5)); 6 | text-underline-offset: $icon-link-underline-offset; 7 | backface-visibility: hidden; 8 | 9 | > .bi { 10 | flex-shrink: 0; 11 | width: $icon-link-icon-size; 12 | height: $icon-link-icon-size; 13 | fill: currentcolor; 14 | @include transition($icon-link-icon-transition); 15 | } 16 | } 17 | 18 | .icon-link-hover { 19 | &:hover, 20 | &:focus-visible { 21 | > .bi { 22 | transform: var(--#{$prefix}icon-link-transform, $icon-link-icon-transform); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /resources/themes/architect/src/components/bootstrap5/helpers/_position.scss: -------------------------------------------------------------------------------- 1 | // Shorthand 2 | 3 | .fixed-top { 4 | position: fixed; 5 | top: 0; 6 | right: 0; 7 | left: 0; 8 | z-index: $zindex-fixed; 9 | } 10 | 11 | .fixed-bottom { 12 | position: fixed; 13 | right: 0; 14 | bottom: 0; 15 | left: 0; 16 | z-index: $zindex-fixed; 17 | } 18 | 19 | // Responsive sticky top and bottom 20 | @each $breakpoint in map-keys($grid-breakpoints) { 21 | @include media-breakpoint-up($breakpoint) { 22 | $infix: breakpoint-infix($breakpoint, $grid-breakpoints); 23 | 24 | .sticky#{$infix}-top { 25 | position: sticky; 26 | top: 0; 27 | z-index: $zindex-sticky; 28 | } 29 | 30 | .sticky#{$infix}-bottom { 31 | position: sticky; 32 | bottom: 0; 33 | z-index: $zindex-sticky; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /resources/themes/architect/src/components/bootstrap5/helpers/_ratio.scss: -------------------------------------------------------------------------------- 1 | // Credit: Nicolas Gallagher and SUIT CSS. 2 | 3 | .ratio { 4 | position: relative; 5 | width: 100%; 6 | 7 | &::before { 8 | display: block; 9 | padding-top: var(--#{$prefix}aspect-ratio); 10 | content: ""; 11 | } 12 | 13 | > * { 14 | position: absolute; 15 | top: 0; 16 | left: 0; 17 | width: 100%; 18 | height: 100%; 19 | } 20 | } 21 | 22 | @each $key, $ratio in $aspect-ratios { 23 | .ratio-#{$key} { 24 | --#{$prefix}aspect-ratio: #{$ratio}; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /resources/themes/architect/src/components/bootstrap5/helpers/_stacks.scss: -------------------------------------------------------------------------------- 1 | // scss-docs-start stacks 2 | .hstack { 3 | display: flex; 4 | flex-direction: row; 5 | align-items: center; 6 | align-self: stretch; 7 | } 8 | 9 | .vstack { 10 | display: flex; 11 | flex: 1 1 auto; 12 | flex-direction: column; 13 | align-self: stretch; 14 | } 15 | // scss-docs-end stacks 16 | -------------------------------------------------------------------------------- /resources/themes/architect/src/components/bootstrap5/helpers/_stretched-link.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Stretched link 3 | // 4 | 5 | .stretched-link { 6 | &::#{$stretched-link-pseudo-element} { 7 | position: absolute; 8 | top: 0; 9 | right: 0; 10 | bottom: 0; 11 | left: 0; 12 | z-index: $stretched-link-z-index; 13 | content: ""; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /resources/themes/architect/src/components/bootstrap5/helpers/_text-truncation.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Text truncation 3 | // 4 | 5 | .text-truncate { 6 | @include text-truncate(); 7 | } 8 | -------------------------------------------------------------------------------- /resources/themes/architect/src/components/bootstrap5/helpers/_visually-hidden.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Visually hidden 3 | // 4 | 5 | .visually-hidden, 6 | .visually-hidden-focusable:not(:focus):not(:focus-within) { 7 | @include visually-hidden(); 8 | } 9 | -------------------------------------------------------------------------------- /resources/themes/architect/src/components/bootstrap5/helpers/_vr.scss: -------------------------------------------------------------------------------- 1 | .vr { 2 | display: inline-block; 3 | align-self: stretch; 4 | width: $vr-border-width; 5 | min-height: 1em; 6 | background-color: currentcolor; 7 | opacity: $hr-opacity; 8 | } 9 | -------------------------------------------------------------------------------- /resources/themes/architect/src/components/bootstrap5/mixins/_alert.scss: -------------------------------------------------------------------------------- 1 | @include deprecate("`alert-variant()`", "v5.3.0", "v6.0.0"); 2 | 3 | // scss-docs-start alert-variant-mixin 4 | @mixin alert-variant($background, $border, $color) { 5 | --#{$prefix}alert-color: #{$color}; 6 | --#{$prefix}alert-bg: #{$background}; 7 | --#{$prefix}alert-border-color: #{$border}; 8 | --#{$prefix}alert-link-color: #{shade-color($color, 20%)}; 9 | 10 | @if $enable-gradients { 11 | background-image: var(--#{$prefix}gradient); 12 | } 13 | 14 | .alert-link { 15 | color: var(--#{$prefix}alert-link-color); 16 | } 17 | } 18 | // scss-docs-end alert-variant-mixin 19 | -------------------------------------------------------------------------------- /resources/themes/architect/src/components/bootstrap5/mixins/_backdrop.scss: -------------------------------------------------------------------------------- 1 | // Shared between modals and offcanvases 2 | @mixin overlay-backdrop($zindex, $backdrop-bg, $backdrop-opacity) { 3 | position: fixed; 4 | top: 0; 5 | left: 0; 6 | z-index: $zindex; 7 | width: 100vw; 8 | height: 100vh; 9 | background-color: $backdrop-bg; 10 | 11 | // Fade for backdrop 12 | &.fade { opacity: 0; } 13 | &.show { opacity: $backdrop-opacity; } 14 | } 15 | -------------------------------------------------------------------------------- /resources/themes/architect/src/components/bootstrap5/mixins/_banner.scss: -------------------------------------------------------------------------------- 1 | @mixin bsBanner($file) { 2 | /*! 3 | * Bootstrap #{$file} v5.3.2 (https://getbootstrap.com/) 4 | * Copyright 2011-2023 The Bootstrap Authors 5 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) 6 | */ 7 | } 8 | -------------------------------------------------------------------------------- /resources/themes/architect/src/components/bootstrap5/mixins/_box-shadow.scss: -------------------------------------------------------------------------------- 1 | @mixin box-shadow($shadow...) { 2 | @if $enable-shadows { 3 | $result: (); 4 | 5 | @each $value in $shadow { 6 | @if $value != null { 7 | $result: append($result, $value, "comma"); 8 | } 9 | @if $value == none and length($shadow) > 1 { 10 | @warn "The keyword 'none' must be used as a single argument."; 11 | } 12 | } 13 | 14 | @if (length($result) > 0) { 15 | box-shadow: $result; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /resources/themes/architect/src/components/bootstrap5/mixins/_caret.scss: -------------------------------------------------------------------------------- 1 | // scss-docs-start caret-mixins 2 | @mixin caret-down($width: $caret-width) { 3 | border-top: $width solid; 4 | border-right: $width solid transparent; 5 | border-bottom: 0; 6 | border-left: $width solid transparent; 7 | } 8 | 9 | @mixin caret-up($width: $caret-width) { 10 | border-top: 0; 11 | border-right: $width solid transparent; 12 | border-bottom: $width solid; 13 | border-left: $width solid transparent; 14 | } 15 | 16 | @mixin caret-end($width: $caret-width) { 17 | border-top: $width solid transparent; 18 | border-right: 0; 19 | border-bottom: $width solid transparent; 20 | border-left: $width solid; 21 | } 22 | 23 | @mixin caret-start($width: $caret-width) { 24 | border-top: $width solid transparent; 25 | border-right: $width solid; 26 | border-bottom: $width solid transparent; 27 | } 28 | 29 | @mixin caret( 30 | $direction: down, 31 | $width: $caret-width, 32 | $spacing: $caret-spacing, 33 | $vertical-align: $caret-vertical-align 34 | ) { 35 | @if $enable-caret { 36 | &::after { 37 | display: inline-block; 38 | margin-left: $spacing; 39 | vertical-align: $vertical-align; 40 | content: ""; 41 | @if $direction == down { 42 | @include caret-down($width); 43 | } @else if $direction == up { 44 | @include caret-up($width); 45 | } @else if $direction == end { 46 | @include caret-end($width); 47 | } 48 | } 49 | 50 | @if $direction == start { 51 | &::after { 52 | display: none; 53 | } 54 | 55 | &::before { 56 | display: inline-block; 57 | margin-right: $spacing; 58 | vertical-align: $vertical-align; 59 | content: ""; 60 | @include caret-start($width); 61 | } 62 | } 63 | 64 | &:empty::after { 65 | margin-left: 0; 66 | } 67 | } 68 | } 69 | // scss-docs-end caret-mixins 70 | -------------------------------------------------------------------------------- /resources/themes/architect/src/components/bootstrap5/mixins/_clearfix.scss: -------------------------------------------------------------------------------- 1 | // scss-docs-start clearfix 2 | @mixin clearfix() { 3 | &::after { 4 | display: block; 5 | clear: both; 6 | content: ""; 7 | } 8 | } 9 | // scss-docs-end clearfix 10 | -------------------------------------------------------------------------------- /resources/themes/architect/src/components/bootstrap5/mixins/_color-mode.scss: -------------------------------------------------------------------------------- 1 | // scss-docs-start color-mode-mixin 2 | @mixin color-mode($mode: light, $root: false) { 3 | @if $color-mode-type == "media-query" { 4 | @if $root == true { 5 | @media (prefers-color-scheme: $mode) { 6 | :root { 7 | @content; 8 | } 9 | } 10 | } @else { 11 | @media (prefers-color-scheme: $mode) { 12 | @content; 13 | } 14 | } 15 | } @else { 16 | [data-bs-theme="#{$mode}"] { 17 | @content; 18 | } 19 | } 20 | } 21 | // scss-docs-end color-mode-mixin 22 | -------------------------------------------------------------------------------- /resources/themes/architect/src/components/bootstrap5/mixins/_color-scheme.scss: -------------------------------------------------------------------------------- 1 | // scss-docs-start mixin-color-scheme 2 | @mixin color-scheme($name) { 3 | @media (prefers-color-scheme: #{$name}) { 4 | @content; 5 | } 6 | } 7 | // scss-docs-end mixin-color-scheme 8 | -------------------------------------------------------------------------------- /resources/themes/architect/src/components/bootstrap5/mixins/_container.scss: -------------------------------------------------------------------------------- 1 | // Container mixins 2 | 3 | @mixin make-container($gutter: $container-padding-x) { 4 | --#{$prefix}gutter-x: #{$gutter}; 5 | --#{$prefix}gutter-y: 0; 6 | width: 100%; 7 | padding-right: calc(var(--#{$prefix}gutter-x) * .5); // stylelint-disable-line function-disallowed-list 8 | padding-left: calc(var(--#{$prefix}gutter-x) * .5); // stylelint-disable-line function-disallowed-list 9 | margin-right: auto; 10 | margin-left: auto; 11 | } 12 | -------------------------------------------------------------------------------- /resources/themes/architect/src/components/bootstrap5/mixins/_deprecate.scss: -------------------------------------------------------------------------------- 1 | // Deprecate mixin 2 | // 3 | // This mixin can be used to deprecate mixins or functions. 4 | // `$enable-deprecation-messages` is a global variable, `$ignore-warning` is a variable that can be passed to 5 | // some deprecated mixins to suppress the warning (for example if the mixin is still be used in the current version of Bootstrap) 6 | @mixin deprecate($name, $deprecate-version, $remove-version, $ignore-warning: false) { 7 | @if ($enable-deprecation-messages != false and $ignore-warning != true) { 8 | @warn "#{$name} has been deprecated as of #{$deprecate-version}. It will be removed entirely in #{$remove-version}."; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /resources/themes/architect/src/components/bootstrap5/mixins/_image.scss: -------------------------------------------------------------------------------- 1 | // Image Mixins 2 | // - Responsive image 3 | // - Retina image 4 | 5 | 6 | // Responsive image 7 | // 8 | // Keep images from scaling beyond the width of their parents. 9 | 10 | @mixin img-fluid { 11 | // Part 1: Set a maximum relative to the parent 12 | max-width: 100%; 13 | // Part 2: Override the height to auto, otherwise images will be stretched 14 | // when setting a width and height attribute on the img element. 15 | height: auto; 16 | } 17 | -------------------------------------------------------------------------------- /resources/themes/architect/src/components/bootstrap5/mixins/_list-group.scss: -------------------------------------------------------------------------------- 1 | @include deprecate("`list-group-item-variant()`", "v5.3.0", "v6.0.0"); 2 | 3 | // List Groups 4 | 5 | // scss-docs-start list-group-mixin 6 | @mixin list-group-item-variant($state, $background, $color) { 7 | .list-group-item-#{$state} { 8 | color: $color; 9 | background-color: $background; 10 | 11 | &.list-group-item-action { 12 | &:hover, 13 | &:focus { 14 | color: $color; 15 | background-color: shade-color($background, 10%); 16 | } 17 | 18 | &.active { 19 | color: $white; 20 | background-color: $color; 21 | border-color: $color; 22 | } 23 | } 24 | } 25 | } 26 | // scss-docs-end list-group-mixin 27 | -------------------------------------------------------------------------------- /resources/themes/architect/src/components/bootstrap5/mixins/_lists.scss: -------------------------------------------------------------------------------- 1 | // Lists 2 | 3 | // Unstyled keeps list items block level, just removes default browser padding and list-style 4 | @mixin list-unstyled { 5 | padding-left: 0; 6 | list-style: none; 7 | } 8 | -------------------------------------------------------------------------------- /resources/themes/architect/src/components/bootstrap5/mixins/_pagination.scss: -------------------------------------------------------------------------------- 1 | // Pagination 2 | 3 | // scss-docs-start pagination-mixin 4 | @mixin pagination-size($padding-y, $padding-x, $font-size, $border-radius) { 5 | --#{$prefix}pagination-padding-x: #{$padding-x}; 6 | --#{$prefix}pagination-padding-y: #{$padding-y}; 7 | @include rfs($font-size, --#{$prefix}pagination-font-size); 8 | --#{$prefix}pagination-border-radius: #{$border-radius}; 9 | } 10 | // scss-docs-end pagination-mixin 11 | -------------------------------------------------------------------------------- /resources/themes/architect/src/components/bootstrap5/mixins/_reset-text.scss: -------------------------------------------------------------------------------- 1 | @mixin reset-text { 2 | font-family: $font-family-base; 3 | // We deliberately do NOT reset font-size or overflow-wrap / word-wrap. 4 | font-style: normal; 5 | font-weight: $font-weight-normal; 6 | line-height: $line-height-base; 7 | text-align: left; // Fallback for where `start` is not supported 8 | text-align: start; 9 | text-decoration: none; 10 | text-shadow: none; 11 | text-transform: none; 12 | letter-spacing: normal; 13 | word-break: normal; 14 | white-space: normal; 15 | word-spacing: normal; 16 | line-break: auto; 17 | } 18 | -------------------------------------------------------------------------------- /resources/themes/architect/src/components/bootstrap5/mixins/_resize.scss: -------------------------------------------------------------------------------- 1 | // Resize anything 2 | 3 | @mixin resizable($direction) { 4 | overflow: auto; // Per CSS3 UI, `resize` only applies when `overflow` isn't `visible` 5 | resize: $direction; // Options: horizontal, vertical, both 6 | } 7 | -------------------------------------------------------------------------------- /resources/themes/architect/src/components/bootstrap5/mixins/_table-variants.scss: -------------------------------------------------------------------------------- 1 | // scss-docs-start table-variant 2 | @mixin table-variant($state, $background) { 3 | .table-#{$state} { 4 | $color: color-contrast(opaque($body-bg, $background)); 5 | $hover-bg: mix($color, $background, percentage($table-hover-bg-factor)); 6 | $striped-bg: mix($color, $background, percentage($table-striped-bg-factor)); 7 | $active-bg: mix($color, $background, percentage($table-active-bg-factor)); 8 | $table-border-color: mix($color, $background, percentage($table-border-factor)); 9 | 10 | --#{$prefix}table-color: #{$color}; 11 | --#{$prefix}table-bg: #{$background}; 12 | --#{$prefix}table-border-color: #{$table-border-color}; 13 | --#{$prefix}table-striped-bg: #{$striped-bg}; 14 | --#{$prefix}table-striped-color: #{color-contrast($striped-bg)}; 15 | --#{$prefix}table-active-bg: #{$active-bg}; 16 | --#{$prefix}table-active-color: #{color-contrast($active-bg)}; 17 | --#{$prefix}table-hover-bg: #{$hover-bg}; 18 | --#{$prefix}table-hover-color: #{color-contrast($hover-bg)}; 19 | 20 | color: var(--#{$prefix}table-color); 21 | border-color: var(--#{$prefix}table-border-color); 22 | } 23 | } 24 | // scss-docs-end table-variant 25 | -------------------------------------------------------------------------------- /resources/themes/architect/src/components/bootstrap5/mixins/_text-truncate.scss: -------------------------------------------------------------------------------- 1 | // Text truncate 2 | // Requires inline-block or block for proper styling 3 | 4 | @mixin text-truncate() { 5 | overflow: hidden; 6 | text-overflow: ellipsis; 7 | white-space: nowrap; 8 | } 9 | -------------------------------------------------------------------------------- /resources/themes/architect/src/components/bootstrap5/mixins/_transition.scss: -------------------------------------------------------------------------------- 1 | // stylelint-disable property-disallowed-list 2 | @mixin transition($transition...) { 3 | @if length($transition) == 0 { 4 | $transition: $transition-base; 5 | } 6 | 7 | @if length($transition) > 1 { 8 | @each $value in $transition { 9 | @if $value == null or $value == none { 10 | @warn "The keyword 'none' or 'null' must be used as a single argument."; 11 | } 12 | } 13 | } 14 | 15 | @if $enable-transitions { 16 | @if nth($transition, 1) != null { 17 | transition: $transition; 18 | } 19 | 20 | @if $enable-reduced-motion and nth($transition, 1) != null and nth($transition, 1) != none { 21 | @media (prefers-reduced-motion: reduce) { 22 | transition: none; 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /resources/themes/architect/src/components/bootstrap5/mixins/_visually-hidden.scss: -------------------------------------------------------------------------------- 1 | // stylelint-disable declaration-no-important 2 | 3 | // Hide content visually while keeping it accessible to assistive technologies 4 | // 5 | // See: https://www.a11yproject.com/posts/2013-01-11-how-to-hide-content/ 6 | // See: https://kittygiraudel.com/2016/10/13/css-hide-and-seek/ 7 | 8 | @mixin visually-hidden() { 9 | width: 1px !important; 10 | height: 1px !important; 11 | padding: 0 !important; 12 | margin: -1px !important; // Fix for https://github.com/twbs/bootstrap/issues/25686 13 | overflow: hidden !important; 14 | clip: rect(0, 0, 0, 0) !important; 15 | white-space: nowrap !important; 16 | border: 0 !important; 17 | 18 | // Fix for positioned table caption that could become anonymous cells 19 | &:not(caption) { 20 | position: absolute !important; 21 | } 22 | } 23 | 24 | // Use to only display content when it's focused, or one of its child elements is focused 25 | // (i.e. when focus is within the element/container that the class was applied to) 26 | // 27 | // Useful for "Skip to main content" links; see https://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1 28 | 29 | @mixin visually-hidden-focusable() { 30 | &:not(:focus):not(:focus-within) { 31 | @include visually-hidden(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /resources/themes/architect/src/components/bootstrap5/utilities/_api.scss: -------------------------------------------------------------------------------- 1 | // Loop over each breakpoint 2 | @each $breakpoint in map-keys($grid-breakpoints) { 3 | 4 | // Generate media query if needed 5 | @include media-breakpoint-up($breakpoint) { 6 | $infix: breakpoint-infix($breakpoint, $grid-breakpoints); 7 | 8 | // Loop over each utility property 9 | @each $key, $utility in $utilities { 10 | // The utility can be disabled with `false`, thus check if the utility is a map first 11 | // Only proceed if responsive media queries are enabled or if it's the base media query 12 | @if type-of($utility) == "map" and (map-get($utility, responsive) or $infix == "") { 13 | @include generate-utility($utility, $infix); 14 | } 15 | } 16 | } 17 | } 18 | 19 | // RFS rescaling 20 | @media (min-width: $rfs-mq-value) { 21 | @each $breakpoint in map-keys($grid-breakpoints) { 22 | $infix: breakpoint-infix($breakpoint, $grid-breakpoints); 23 | 24 | @if (map-get($grid-breakpoints, $breakpoint) < $rfs-breakpoint) { 25 | // Loop over each utility property 26 | @each $key, $utility in $utilities { 27 | // The utility can be disabled with `false`, thus check if the utility is a map first 28 | // Only proceed if responsive media queries are enabled or if it's the base media query 29 | @if type-of($utility) == "map" and map-get($utility, rfs) and (map-get($utility, responsive) or $infix == "") { 30 | @include generate-utility($utility, $infix, true); 31 | } 32 | } 33 | } 34 | } 35 | } 36 | 37 | 38 | // Print utilities 39 | @media print { 40 | @each $key, $utility in $utilities { 41 | // The utility can be disabled with `false`, thus check if the utility is a map first 42 | // Then check if the utility needs print styles 43 | @if type-of($utility) == "map" and map-get($utility, print) == true { 44 | @include generate-utility($utility, "-print"); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /resources/themes/architect/src/components/hamburgers/types/_elastic.scss: -------------------------------------------------------------------------------- 1 | @if index($hamburger-types, elastic) { 2 | /* 3 | * Elastic 4 | */ 5 | .hamburger--elastic { 6 | .hamburger-inner { 7 | top: divide($hamburger-layer-height, 2); 8 | transition-duration: 0.275s; 9 | transition-timing-function: cubic-bezier(0.68, -0.55, 0.265, 1.55); 10 | 11 | &::before { 12 | top: $hamburger-layer-height + $hamburger-layer-spacing; 13 | transition: opacity 0.125s 0.275s ease; 14 | } 15 | 16 | &::after { 17 | top: ($hamburger-layer-height * 2) + ($hamburger-layer-spacing * 2); 18 | transition: transform 0.275s cubic-bezier(0.68, -0.55, 0.265, 1.55); 19 | } 20 | } 21 | 22 | &.is-active { 23 | .hamburger-inner { 24 | $y-offset: $hamburger-layer-spacing + $hamburger-layer-height; 25 | 26 | transform: translate3d(0, $y-offset, 0) rotate(135deg); 27 | transition-delay: 0.075s; 28 | 29 | &::before { 30 | transition-delay: 0s; 31 | opacity: 0; 32 | } 33 | 34 | &::after { 35 | transform: translate3d(0, $y-offset * -2, 0) rotate(-270deg); 36 | transition-delay: 0.075s; 37 | } 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /resources/themes/architect/src/components/icons/_p7icons.scss: -------------------------------------------------------------------------------- 1 | $pe-7s-font-path: "~pe7-icon/dist/fonts"; 2 | 3 | @import "~pe7-icon/dist/scss/pe-icon-7-stroke.scss"; -------------------------------------------------------------------------------- /resources/themes/architect/src/components/icons/fontawesome/_fontawesome.scss: -------------------------------------------------------------------------------- 1 | // Fontawesome 2 | 3 | $fa-font-path: "~@fortawesome/fontawesome-free/webfonts"; 4 | 5 | @import "~@fortawesome/fontawesome-free/scss/fontawesome.scss"; 6 | 7 | // You can include all the other styles the same as before 8 | @import "~@fortawesome/fontawesome-free/scss/solid.scss"; 9 | @import "~@fortawesome/fontawesome-free/scss/brands.scss"; 10 | 11 | .fa-2x { 12 | line-height: 2; 13 | } -------------------------------------------------------------------------------- /resources/themes/architect/src/elements/_forms.scss: -------------------------------------------------------------------------------- 1 | // Input groups 2 | 3 | .input-group { 4 | .input-group-prepend { 5 | div:not([class]) .react-datepicker__input-container, 6 | & + div .react-datepicker__input-container { 7 | .form-control { 8 | @include border-start-radius(0); 9 | @include border-end-radius($input-border-radius !important); 10 | } 11 | } 12 | } 13 | 14 | & > div:not([class]) { 15 | position: relative; 16 | flex: 1 1 auto; 17 | width: 1%; 18 | 19 | & .react-datepicker__input-container { 20 | .form-control { 21 | @include border-end-radius(0); 22 | } 23 | 24 | } 25 | } 26 | } 27 | 28 | .input-group { 29 | .input-group-prepend { 30 | & + div { 31 | position: relative; 32 | flex: 1 1 auto; 33 | width: 1%; 34 | } 35 | } 36 | 37 | & > .react-datepicker-wrapper { 38 | position: relative; 39 | flex: 1 1 auto; 40 | width: 1%; 41 | 42 | & > .react-datepicker__input-container > .form-control { 43 | @include border-end-radius(0); 44 | } 45 | } 46 | } 47 | 48 | // Forms Legend 49 | 50 | legend { 51 | font-size: $font-size-base; 52 | font-weight: bold; 53 | } 54 | 55 | // Headings 56 | 57 | .form-heading { 58 | font-size: $font-size-lg; 59 | margin: 0; 60 | color: $primary; 61 | 62 | p { 63 | color: $gray-600; 64 | padding: 0.3rem 0 0; 65 | font-size: $font-size-base; 66 | } 67 | } 68 | 69 | .custom-select { 70 | -webkit-appearance: none; 71 | -moz-appearance: none; 72 | } -------------------------------------------------------------------------------- /resources/themes/architect/src/elements/_modals.scss: -------------------------------------------------------------------------------- 1 | // Modals 2 | 3 | .modal-header, 4 | .modal-footer { 5 | background: $gray-100; 6 | } 7 | 8 | .modal-footer { 9 | @include border-bottom-radius($border-radius); 10 | } 11 | 12 | .modal-dialog { 13 | box-shadow: $box-shadow-lg-default; 14 | @include border-radius($border-radius); 15 | } -------------------------------------------------------------------------------- /resources/themes/architect/src/elements/listgroup.scss: -------------------------------------------------------------------------------- 1 | // List Group 2 | 3 | .todo-list-wrapper { 4 | .todo-indicator { 5 | position: absolute; 6 | width: 4px; 7 | height: 60%; 8 | @include border-radius($border-radius-lg); 9 | left: divide($card-spacer-x, 2); 10 | top: 20%; 11 | opacity: .6; 12 | transition: opacity .2s; 13 | } 14 | 15 | .list-group-item { 16 | &:hover { 17 | .todo-indicator { 18 | opacity: .9; 19 | } 20 | } 21 | } 22 | 23 | .custom-control, 24 | input[checkbox] { 25 | margin-left: divide($card-spacer-x, 2); 26 | } 27 | } 28 | 29 | .list-group-flush + .card-footer { 30 | border-top: 0; 31 | } 32 | 33 | .rm-list-borders { 34 | .list-group-item { 35 | border: 0; 36 | padding: divide($card-spacer-y, 1.5) 0; 37 | } 38 | } 39 | 40 | .rm-list-borders-scroll { 41 | .list-group-item { 42 | border: 0; 43 | padding-right: ($card-spacer-y * 1.5); 44 | } 45 | } -------------------------------------------------------------------------------- /resources/themes/architect/src/layout/_layout-variables.scss: -------------------------------------------------------------------------------- 1 | // Variables 2 | 3 | $spacer-lg: 3rem; 4 | $spacer-sm: 1.5rem; 5 | 6 | $layout-spacer-lg: 3rem; 7 | $layout-spacer-x: 1.5rem; 8 | 9 | $app-sidebar-width: 250px; 10 | $app-sidebar-width-collapsed: 80px; 11 | 12 | $logo-height: 23px; 13 | $logo-width: 97px; 14 | 15 | $app-header-height: 60px; 16 | -------------------------------------------------------------------------------- /resources/themes/architect/src/layout/_layout.scss: -------------------------------------------------------------------------------- 1 | // Variables 2 | @import "layout-variables"; 3 | @import "generic/generic-base"; 4 | @import "generic/animations"; 5 | @import "header/header-base"; 6 | @import "sidebar/sidebar-base"; 7 | @import "main/main-base"; 8 | @import "footer/footer-base"; 9 | @import "elements/page-title/page-title-base"; 10 | @import "elements/search-box/search-box"; -------------------------------------------------------------------------------- /resources/themes/architect/src/layout/footer/_footer-base.scss: -------------------------------------------------------------------------------- 1 | // Footer base 2 | 3 | .app-footer { 4 | height: $app-header-height; 5 | 6 | .app-footer__inner { 7 | padding: 0 $layout-spacer-x 0 divide($layout-spacer-x, 2); 8 | height: $app-header-height; 9 | 10 | display: flex; 11 | align-content: center; 12 | align-items: center; 13 | 14 | .app-footer-left { 15 | display: flex; 16 | align-items: center; 17 | } 18 | 19 | .app-footer-right { 20 | margin-left: auto; 21 | display: flex; 22 | } 23 | } 24 | } 25 | 26 | // Footer Dots Section 27 | 28 | .footer-dots { 29 | display: flex; 30 | align-items: center; 31 | align-content: center; 32 | 33 | .dots-separator { 34 | height: 40px; 35 | margin: 0 divide($layout-spacer-x, 2.5); 36 | width: 1px; 37 | background: $gray-200; 38 | } 39 | } 40 | 41 | .dot-btn-wrapper { 42 | padding: .5rem; 43 | position: relative; 44 | display: flex; 45 | opacity: .7; 46 | transition: opacity .2s; 47 | cursor: pointer; 48 | text-decoration: none; 49 | 50 | .badge-abs { 51 | right: 50%; 52 | 53 | &.badge-dot-sm { 54 | top: -2px; 55 | margin-right: -3px; 56 | } 57 | } 58 | 59 | .dot-btn-icon { 60 | font-size: 1.8rem; 61 | } 62 | 63 | &:hover { 64 | text-decoration: none; 65 | opacity: 1; 66 | } 67 | } 68 | 69 | // Footer Modifiers 70 | 71 | // @import "fixed-footer"; 72 | -------------------------------------------------------------------------------- /resources/themes/architect/src/layout/generic/_animations.scss: -------------------------------------------------------------------------------- 1 | // Sidebar Animation 2 | 3 | .SidebarAnimation-appear { 4 | transform: translateX(-30px); 5 | opacity: 0; 6 | 7 | &.SidebarAnimation-appear-active { 8 | opacity: 1; 9 | transform: translateX(0); 10 | transition: all .4s linear; 11 | } 12 | } 13 | 14 | // Tabs Animation 15 | 16 | .TabsAnimation-appear { 17 | @extend .animated !optional; 18 | @extend .fadeInUp !optional; 19 | } 20 | 21 | // Header Animation 22 | 23 | .HeaderAnimation-appear { 24 | transform: translateY(-30px); 25 | opacity: 0; 26 | 27 | &.HeaderAnimation-appear-active { 28 | opacity: 1; 29 | transform: translateY(0); 30 | transition: all .4s linear; 31 | } 32 | } 33 | 34 | // Main Animation 35 | 36 | .MainAnimation-appear { 37 | transform: translateY(-30px); 38 | opacity: 0; 39 | 40 | &.MainAnimation-appear-active { 41 | opacity: 1; 42 | transform: translateY(0); 43 | transition: all .4s linear; 44 | } 45 | } -------------------------------------------------------------------------------- /resources/themes/architect/src/layout/generic/_generic-base.scss: -------------------------------------------------------------------------------- 1 | // General 2 | 3 | a, 4 | button, 5 | .btn { 6 | outline: none !important; 7 | } 8 | 9 | .app-container { 10 | display: flex; 11 | min-height: 100vh; 12 | flex-direction: column; 13 | margin: 0; 14 | } 15 | 16 | .icon-anim-pulse { 17 | animation: pulse_animation; 18 | animation-duration: 1000ms; 19 | animation-iteration-count: infinite; 20 | animation-timing-function: linear; 21 | } 22 | 23 | @keyframes pulse_animation { 24 | 0% { 25 | transform: scale(1); 26 | } 27 | 30% { 28 | transform: scale(1.1); 29 | } 30 | 40% { 31 | transform: scale(1.21); 32 | } 33 | 50% { 34 | transform: scale(1); 35 | } 36 | 60% { 37 | transform: scale(1); 38 | } 39 | 70% { 40 | transform: scale(1.09); 41 | } 42 | 80% { 43 | transform: scale(1.05); 44 | } 45 | 100% { 46 | transform: scale(1); 47 | } 48 | } -------------------------------------------------------------------------------- /resources/themes/architect/src/layout/header/_header-base.scss: -------------------------------------------------------------------------------- 1 | // Header Base 2 | 3 | .app-header { 4 | height: $app-header-height; 5 | display: flex; 6 | align-items: center; 7 | align-content: center; 8 | position: relative; 9 | z-index: 14; 10 | transition: all .2s; 11 | 12 | &.header-shadow { 13 | box-shadow: $box-shadow-default; 14 | } 15 | 16 | .app-header__content { 17 | display: flex; 18 | align-items: center; 19 | align-content: center; 20 | flex: 1; 21 | padding: 0 $layout-spacer-x; 22 | height: $app-header-height; 23 | 24 | .app-header-left { 25 | display: flex; 26 | align-items: center; 27 | } 28 | 29 | .app-header-right { 30 | align-items: center; 31 | display: flex; 32 | margin-left: auto; 33 | } 34 | } 35 | 36 | .header-user-info { 37 | & > .widget-heading, 38 | & > .widget-subheading { 39 | white-space: nowrap; 40 | } 41 | 42 | & > .widget-subheading { 43 | font-size: $font-size-xs; 44 | } 45 | } 46 | } 47 | 48 | .app-header__logo { 49 | padding: 0 $layout-spacer-x; 50 | height: $app-header-height; 51 | width: $app-sidebar-width; 52 | display: flex; 53 | align-items: center; 54 | transition: width .2s; 55 | 56 | .logo-src { 57 | height: $logo-height; 58 | width: $logo-width; 59 | } 60 | } 61 | 62 | .app-header__menu, 63 | .app-header__mobile-menu { 64 | display: none; 65 | padding: 0 $layout-spacer-x; 66 | height: $app-header-height; 67 | align-items: center; 68 | } 69 | 70 | // Header Modifiers 71 | 72 | @import "modifiers/fixed-header"; 73 | //@import "modifiers/header-dots"; 74 | //@import "modifiers/header-megamenu"; 75 | //@import "modifiers/header-buttons"; 76 | 77 | // Header Themes 78 | 79 | @import "themes/header-light"; 80 | @import "themes/header-dark"; 81 | -------------------------------------------------------------------------------- /resources/themes/architect/src/layout/header/modifiers/_fixed-header.scss: -------------------------------------------------------------------------------- 1 | // Fixed Header 2 | 3 | .fixed-header { 4 | .app-header { 5 | position: fixed; 6 | width: 100%; 7 | top: 0; 8 | 9 | .app-header__logo { 10 | visibility: visible; 11 | } 12 | } 13 | 14 | .app-main { 15 | padding-top: $app-header-height; 16 | } 17 | 18 | &:not(.fixed-sidebar):not(.closed-sidebar) { 19 | .app-sidebar { 20 | .app-header__logo { 21 | visibility: hidden; 22 | } 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /resources/themes/architect/src/layout/main/_main-base.scss: -------------------------------------------------------------------------------- 1 | // Main Base 2 | 3 | .app-main { 4 | // flex: 1; 5 | // display: flex; 6 | // z-index: 8; 7 | position: relative; 8 | 9 | .app-main__outer { 10 | flex: 1; 11 | flex-direction: column; 12 | display: flex; 13 | z-index: 12; 14 | } 15 | 16 | .app-main__inner { 17 | padding: $grid-gutter-width $grid-gutter-width 0; 18 | flex: 1; 19 | } 20 | } 21 | 22 | // Themes 23 | 24 | @import "themes/main-white"; 25 | //@import "themes/main-gray"; 26 | //@import "themes/main-inverted-blue"; 27 | //@import "themes/main-inverted-black"; 28 | -------------------------------------------------------------------------------- /resources/themes/architect/src/layout/main/themes/_main-white.scss: -------------------------------------------------------------------------------- 1 | // Theme White 2 | 3 | // Variables 4 | 5 | $app-container-bg: #f1f4f6; 6 | $app-sidebar-bg: #ffffff; 7 | $app-header-bg: #fafbfc; 8 | $app-header-logo-bg: rgba(255, 255, 255, .9); 9 | 10 | // Content 11 | 12 | .app-theme-white { 13 | 14 | &.app-container { 15 | background: $app-container-bg; 16 | } 17 | 18 | .app-sidebar { 19 | background: $app-sidebar-bg; 20 | } 21 | 22 | .app-page-title { 23 | background: rgba(255, 255, 255, .45); 24 | } 25 | 26 | .app-footer .app-footer__inner, 27 | .app-header { 28 | background: $app-header-bg; 29 | } 30 | 31 | &.fixed-header { 32 | .app-header__logo { 33 | background: rgba($app-header-bg, .1); 34 | } 35 | } 36 | 37 | } -------------------------------------------------------------------------------- /resources/themes/architect/src/layout/sidebar/_sidebar-base.scss: -------------------------------------------------------------------------------- 1 | // Sidebar Base 2 | 3 | .app-sidebar { 4 | width: $app-sidebar-width; 5 | display: flex; 6 | z-index: 11; 7 | overflow: hidden; 8 | min-width: $app-sidebar-width; 9 | position: relative; 10 | flex: 0 0 $app-sidebar-width; 11 | margin-top: -$app-header-height; 12 | padding-top: $app-header-height; 13 | transition: all .2s; 14 | 15 | .app-sidebar__inner { 16 | padding: 2px ($layout-spacer-x) $layout-spacer-x; 17 | } 18 | 19 | .scrollbar-sidebar { 20 | z-index: 15; 21 | width: 100%; 22 | } 23 | 24 | .app-sidebar-bg { 25 | position: absolute; 26 | left: 0; 27 | top: 0; 28 | height: 100%; 29 | width: 100%; 30 | opacity: 0.05; 31 | background-size: cover; 32 | z-index: 10; 33 | } 34 | 35 | .app-header__logo { 36 | position: absolute; 37 | left: 0; 38 | top: 0; 39 | display: none; 40 | z-index: 11; 41 | } 42 | 43 | &.sidebar-shadow { 44 | box-shadow: 7px 0 60px rgba(0, 0, 0, 0.05); 45 | } 46 | } 47 | 48 | .app-sidebar__heading { 49 | text-transform: uppercase; 50 | font-size: $font-size-xs; 51 | margin: divide($layout-spacer-x, 2) 0; 52 | font-weight: bold; 53 | color: $primary; 54 | white-space: nowrap; 55 | position: relative; 56 | } 57 | 58 | .sidebar-mobile-overlay { 59 | display: none; 60 | position: fixed; 61 | width: 100%; 62 | height: 100%; 63 | background: #333; 64 | opacity: .6; 65 | left: 0; 66 | top: 0; 67 | z-index: 12; 68 | } 69 | 70 | // Sidebar Components 71 | 72 | @import "modifiers/navmenu-vertical"; 73 | 74 | // Sidebar Modifiers 75 | 76 | @import "themes/sidebar-light"; 77 | // @import "themes/sidebar-dark"; 78 | 79 | @import "modifiers/fixed-sidebar"; 80 | @import "modifiers/closed-sidebar"; 81 | -------------------------------------------------------------------------------- /resources/themes/architect/src/layout/sidebar/modifiers/_fixed-sidebar.scss: -------------------------------------------------------------------------------- 1 | // Fixed Sidebar 2 | 3 | .fixed-sidebar { 4 | .app-sidebar { 5 | position: fixed; 6 | height: 100vh; 7 | } 8 | 9 | .app-main { 10 | 11 | .app-main__outer { 12 | z-index: 9; 13 | padding-left: $app-sidebar-width; 14 | } 15 | 16 | } 17 | 18 | &.fixed-header { 19 | .app-sidebar { 20 | .app-header__logo { 21 | display: none; 22 | } 23 | } 24 | } 25 | 26 | &:not(.fixed-header) { 27 | .app-sidebar { 28 | .app-header__logo { 29 | display: flex; 30 | } 31 | } 32 | 33 | .app-header { 34 | 35 | margin-left: $app-sidebar-width; 36 | 37 | .app-header__logo { 38 | display: none; 39 | } 40 | } 41 | 42 | .app-main { 43 | //z-index: 12; 44 | } 45 | } 46 | 47 | &.closed-sidebar { 48 | &:not(.fixed-header) { 49 | 50 | .app-header { 51 | margin-left: $app-sidebar-width-collapsed; 52 | } 53 | 54 | .app-sidebar { 55 | 56 | .app-header__logo { 57 | width: $app-sidebar-width-collapsed; 58 | padding: 0; 59 | 60 | .logo-src { 61 | display: none; 62 | } 63 | 64 | .header__pane { 65 | margin-right: auto; 66 | } 67 | } 68 | } 69 | } 70 | } 71 | } -------------------------------------------------------------------------------- /resources/themes/architect/src/layout/sidebar/themes/_sidebar-dark.scss: -------------------------------------------------------------------------------- 1 | // Sidebar Light 2 | 3 | .app-sidebar { 4 | &.sidebar-text-dark { 5 | border-right: 0 !important; 6 | 7 | .app-sidebar__heading { 8 | color: rgba(0, 0, 0, .6); 9 | 10 | &::before { 11 | background: rgba(0, 0, 0, 0.5) !important; 12 | } 13 | } 14 | 15 | .vertical-nav-menu { 16 | li { 17 | a { 18 | color: rgba(0, 0, 0, 0.6); 19 | i.metismenu-icon { 20 | opacity: .5; 21 | } 22 | 23 | i.metismenu-state-icon { 24 | opacity: .5; 25 | } 26 | 27 | &:hover { 28 | background: rgba(0, 0, 0, 0.15); 29 | color: rgba(0, 0, 0, 0.7); 30 | 31 | i.metismenu-icon { 32 | opacity: .7; 33 | } 34 | 35 | i.metismenu-state-icon { 36 | opacity: 1; 37 | } 38 | } 39 | } 40 | 41 | a.mm-active { 42 | color: rgba(0, 0, 0, 0.7); 43 | background: rgba(0, 0, 0, 0.15); 44 | } 45 | } 46 | 47 | ul { 48 | &:before { 49 | background: rgba(0, 0, 0, 0.1); 50 | } 51 | 52 | & > li > a { 53 | color: rgba(0, 0, 0, 0.4); 54 | 55 | &:hover { 56 | color: rgba(0, 0, 0, 0.7); 57 | } 58 | 59 | &.mm-active { 60 | color: rgba(0, 0, 0, 0.7); 61 | background: rgba(0, 0, 0, 0.15); 62 | } 63 | } 64 | } 65 | } 66 | 67 | .ps__thumb-y { 68 | background: rgba(0, 0, 0, .3); 69 | } 70 | 71 | .ps__rail-y:hover { 72 | .ps__thumb-y { 73 | background: rgba(0, 0, 0, .2); 74 | } 75 | } 76 | 77 | .app-header__logo { 78 | 79 | .hamburger-inner, 80 | .hamburger-inner::before, 81 | .hamburger-inner::after { 82 | background-color: rgba(0, 0, 0, .8); 83 | } 84 | } 85 | } 86 | } -------------------------------------------------------------------------------- /resources/themes/architect/src/layout/sidebar/themes/_sidebar-light.scss: -------------------------------------------------------------------------------- 1 | // Sidebar Light 2 | 3 | .app-sidebar { 4 | &.sidebar-text-light { 5 | border-right: 0 !important; 6 | 7 | .app-sidebar__heading { 8 | color: rgba(255, 255, 255, .6); 9 | 10 | &::before { 11 | background: rgba(255, 255, 255, 0.5) !important; 12 | } 13 | } 14 | 15 | .vertical-nav-menu { 16 | li { 17 | a { 18 | color: rgba(255, 255, 255, 0.7); 19 | i.metismenu-icon { 20 | opacity: .5; 21 | } 22 | 23 | i.metismenu-state-icon { 24 | opacity: .5; 25 | } 26 | 27 | &:hover { 28 | background: rgba(255, 255, 255, 0.15); 29 | color: rgba(255, 255, 255, 1); 30 | 31 | i.metismenu-icon { 32 | opacity: .8; 33 | } 34 | 35 | i.metismenu-state-icon { 36 | opacity: 1; 37 | } 38 | } 39 | } 40 | 41 | a.mm-active { 42 | color: rgba(255, 255, 255, 0.7); 43 | background: rgba(255, 255, 255, 0.15); 44 | } 45 | } 46 | 47 | ul { 48 | &:before { 49 | background: rgba(255, 255, 255, 0.1); 50 | } 51 | 52 | & > li > a { 53 | color: rgba(255, 255, 255, 0.6); 54 | 55 | &:hover { 56 | color: rgba(255, 255, 255, 1); 57 | } 58 | 59 | &.mm-active { 60 | color: rgba(255, 255, 255, 1); 61 | background: rgba(255, 255, 255, 0.15); 62 | } 63 | } 64 | } 65 | } 66 | 67 | .ps__thumb-y { 68 | background: rgba(255, 255, 255, .3); 69 | } 70 | 71 | .ps__rail-y:hover { 72 | .ps__thumb-y { 73 | background: rgba(255, 255, 255, .2); 74 | } 75 | } 76 | 77 | .app-header__logo { 78 | .logo-src { 79 | } 80 | 81 | .hamburger-inner, 82 | .hamburger-inner::before, 83 | .hamburger-inner::after { 84 | background-color: rgba(255, 255, 255, .8); 85 | } 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /resources/themes/architect/src/themes/_layout-variables.scss: -------------------------------------------------------------------------------- 1 | // Default 2 | @import "default/variables"; 3 | 4 | // Black 5 | 6 | //@import "black/variables"; 7 | 8 | // Blue Alternate 9 | 10 | //@import "blue-alt/variables"; 11 | 12 | // Dark 13 | 14 | //@import "dark/variables"; 15 | 16 | // Green 17 | 18 | //@import "green/variables"; 19 | 20 | // Orange 21 | 22 | //@import "orange/variables"; 23 | 24 | // Purple 25 | 26 | //@import "purple/variables"; 27 | 28 | // Purple Alternate 29 | 30 | //@import "purple-alt/variables"; 31 | 32 | // Red 33 | 34 | //@import "red/variables"; -------------------------------------------------------------------------------- /resources/themes/architect/src/utils/_animate-override.scss: -------------------------------------------------------------------------------- 1 | @use "sass:math"; 2 | 3 | @if $use-lightSpeedIn == true { 4 | @-webkit-keyframes lightSpeedIn { 5 | 0% { -webkit-transform: translateX(100%) skewX(-$base-degrees); opacity: 0; } 6 | 60% { -webkit-transform: translateX(-20%) skewX($base-degrees); opacity: 1; } 7 | 80% { -webkit-transform: translateX(0%) skewX(calc(-1 * $base-degrees / 2)); opacity: 1; } 8 | 100% { -webkit-transform: translateX(0%) skewX(0deg); opacity: 1; } 9 | } 10 | 11 | @keyframes lightSpeedIn { 12 | 0% { transform: translateX(100%) skewX(-$base-degrees); opacity: 0; } 13 | 60% { transform: translateX(-20%) skewX($base-degrees); opacity: 1; } 14 | 80% { transform: translateX(0%) skewX(calc(-1 * $base-degrees / 2)); opacity: 1; } 15 | 100% { transform: translateX(0%) skewX(0deg); opacity: 1; } 16 | } 17 | 18 | .lightSpeedIn { 19 | @include animate-prefixer(animation-name, lightSpeedIn); 20 | @include animate-prefixer(animation-timing-function, $base-timing-function-out); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /resources/themes/architect/src/utils/_comps-animations.scss: -------------------------------------------------------------------------------- 1 | // Common Comps Animations 2 | 3 | $base-duration: .2s; 4 | $base-distance: 10px; 5 | $base-fill-mode: both; 6 | 7 | // Dropdown Animation 8 | 9 | .dropdown-menu { 10 | &.show { 11 | animation: fade-in2 .2s cubic-bezier(0.390, 0.575, 0.565, 1.000) both; 12 | } 13 | } 14 | 15 | .popover { 16 | &:not([data-placement^="top"]).show { 17 | animation: fade-in2 .2s cubic-bezier(0.390, 0.575, 0.565, 1.000) both; 18 | } 19 | } 20 | 21 | .dropdown-menu { 22 | &[data-placement^="top"].show { 23 | animation: fade-in3 .2s cubic-bezier(0.390, 0.575, 0.565, 1.000) both; 24 | bottom: auto !important; 25 | top: auto !important; 26 | } 27 | } 28 | 29 | @keyframes fade-in2 { 30 | 0% { 31 | margin-top: -50px; 32 | visibility: hidden; 33 | opacity: 0; 34 | } 35 | 100% { 36 | margin-top: 0px; 37 | visibility: visible; 38 | opacity: 1; 39 | } 40 | } 41 | 42 | .form-control { 43 | transition: all .2s; 44 | } -------------------------------------------------------------------------------- /resources/themes/architect/src/utils/helpers/_grayscale.scss: -------------------------------------------------------------------------------- 1 | // Grayscale Filter 2 | 3 | .filter-grayscale-5 { 4 | filter: grayscale(5%) !important; 5 | } 6 | 7 | .filter-grayscale-10 { 8 | filter: grayscale(10%) !important; 9 | } 10 | 11 | .filter-grayscale-20 { 12 | filter: grayscale(20%) !important; 13 | } 14 | 15 | .filter-grayscale-30 { 16 | filter: grayscale(30%) !important; 17 | } 18 | 19 | .filter-grayscale-40 { 20 | filter: grayscale(40%) !important; 21 | } 22 | 23 | .filter-grayscale-50 { 24 | filter: grayscale(50%) !important; 25 | } 26 | 27 | .filter-grayscale-80 { 28 | filter: grayscale(80%) !important; 29 | } 30 | 31 | .filter-grayscale-100 { 32 | filter: grayscale(100%) !important; 33 | } -------------------------------------------------------------------------------- /resources/themes/architect/src/utils/helpers/_opacity.scss: -------------------------------------------------------------------------------- 1 | // Opacity 2 | 3 | .opacity-01 { 4 | opacity: .01 !important; 5 | } 6 | 7 | .opacity-02 { 8 | opacity: .02 !important; 9 | } 10 | 11 | .opacity-03 { 12 | opacity: .03 !important; 13 | } 14 | 15 | .opacity-04 { 16 | opacity: .04 !important; 17 | } 18 | 19 | .opacity-05 { 20 | opacity: .05 !important; 21 | } 22 | 23 | .opacity-06 { 24 | opacity: .06 !important; 25 | } 26 | 27 | .opacity-07 { 28 | opacity: .07 !important; 29 | } 30 | 31 | .opacity-08 { 32 | opacity: .08 !important; 33 | } 34 | 35 | .opacity-09 { 36 | opacity: .09 !important; 37 | } 38 | 39 | .opacity-1 { 40 | opacity: .1 !important; 41 | } 42 | 43 | .opacity-15 { 44 | opacity: .15 !important; 45 | } 46 | 47 | .opacity-2 { 48 | opacity: .2 !important; 49 | } 50 | 51 | .opacity-3 { 52 | opacity: .3 !important; 53 | } 54 | 55 | .opacity-4 { 56 | opacity: .4 !important; 57 | } 58 | 59 | .opacity-5 { 60 | opacity: .5 !important; 61 | } 62 | 63 | .opacity-6 { 64 | opacity: .6 !important; 65 | } 66 | 67 | .opacity-7 { 68 | opacity: .7 !important; 69 | } 70 | 71 | .opacity-8 { 72 | opacity: .8 !important; 73 | } 74 | 75 | .opacity-9 { 76 | opacity: .9 !important; 77 | } 78 | 79 | .opacity-10 { 80 | opacity: 1 !important; 81 | } -------------------------------------------------------------------------------- /resources/themes/architect/src/widgets/content-boxes/_content-boxes.scss: -------------------------------------------------------------------------------- 1 | // Content Boxes 2 | 3 | // Variables 4 | 5 | $widget-spacer: $spacer; 6 | 7 | .widget-content { 8 | padding: $widget-spacer; 9 | flex-direction: row; 10 | align-items: center; 11 | 12 | .widget-content-wrapper { 13 | display: flex; 14 | flex: 1; 15 | position: relative; 16 | align-items: center; 17 | } 18 | 19 | .widget-content-left { 20 | 21 | .widget-heading { 22 | opacity: .8; 23 | font-weight: bold; 24 | } 25 | 26 | .widget-subheading { 27 | opacity: .5; 28 | } 29 | } 30 | 31 | .widget-content-right { 32 | margin-left: auto; 33 | } 34 | 35 | .widget-numbers { 36 | font-weight: bold; 37 | font-size: 1.8rem; 38 | display: block; 39 | } 40 | 41 | .widget-content-outer { 42 | display: flex; 43 | flex: 1; 44 | flex-direction: column; 45 | } 46 | 47 | .widget-progress-wrapper { 48 | margin-top: $widget-spacer; 49 | 50 | .progress-sub-label { 51 | margin-top: divide($widget-spacer, 3); 52 | opacity: .5; 53 | display: flex; 54 | align-content: center; 55 | align-items: center; 56 | 57 | .sub-label-left { 58 | 59 | } 60 | 61 | .sub-label-right { 62 | margin-left: auto; 63 | } 64 | } 65 | } 66 | 67 | .widget-content-right { 68 | &.widget-content-actions { 69 | visibility: hidden; 70 | opacity: 0; 71 | transition: opacity .2s; 72 | } 73 | } 74 | 75 | &:hover { 76 | .widget-content-right { 77 | &.widget-content-actions { 78 | visibility: visible; 79 | opacity: 1; 80 | } 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /resources/themes/architect/views/auth/partials/scripts.blade.php: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leenooks/phpLDAPadmin/b08de519d4091fe5f89192b6e7fa145f2167ae6a/resources/themes/architect/views/auth/partials/scripts.blade.php -------------------------------------------------------------------------------- /resources/themes/architect/views/layouts/app.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | @section('htmlheader') 4 | @include('architect::layouts.partials.htmlheader') 5 | @show 6 | 7 | 8 | 9 | @include('architect::layouts.partials.topmenu') 10 | 11 | @includeIf('architect::layouts.partials.controlsidebar') 12 | 13 | 14 | @include('architect::layouts.partials.sidebarmenu') 15 | 16 | 17 | 18 | 19 | @if(trim($__env->yieldContent('page_title'))) 20 | @include('architect::layouts.partials.contentheader') 21 | @endif 22 | 23 | 24 | 25 | 26 | 27 | @yield('main-content') 28 | 29 | 30 | 31 | 32 | 33 | @include('architect::layouts.partials.contentfooter') 34 | 35 | 36 | 37 | 38 | @yield('page-modals') 39 | 40 | @section('scripts') 41 | @include('architect::layouts.partials.scripts') 42 | 43 | @yield('page-scripts') 44 | @show 45 | 46 | -------------------------------------------------------------------------------- /resources/themes/architect/views/layouts/auth.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | @section('htmlheader') 4 | @include('architect::layouts.partials.htmlheader') 5 | @show 6 | 7 | 8 | 9 | @yield('content') 10 | 11 | 12 | @section('scripts') 13 | @include('architect::auth.partials.scripts') 14 | 15 | @yield('page-scripts') 16 | @show 17 | 18 | -------------------------------------------------------------------------------- /resources/themes/architect/views/layouts/error.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | @section('htmlheader') 4 | @include('architect::layouts.partials.htmlheader') 5 | @show 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | @yield('title') 21 | 22 | 23 | 24 | 25 | @yield('error') 26 | 27 | 28 | 29 | Configuration 30 | {{ $x=config('ldap.default') }} 31 | 32 | 33 | Host 34 | {{ ($y=collect(config('ldap.connections.'.$x.'.hosts')))->join(',') }} (IP: {!! $y->transform(fn($item)=>collect(@dns_get_record($item,DNS_A|DNS_AAAA))->transform(fn($item)=>Arr::get($item,'ip',Arr::get($item,'ipv6')))->filter()->join(','))->join(',') !!}) 35 | 36 | 37 | Port 38 | {{ config('ldap.connections.'.$x.'.port') }} 39 | 40 | 41 | Message 42 | @yield('content') 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /resources/themes/architect/views/layouts/partials/contentfooter.blade.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /resources/themes/architect/views/layouts/partials/contentheader.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | @if(trim($__env->yieldContent('page_icon'))) 5 | 6 | 7 | 8 | @endif 9 | 10 | @yield('page_title','Page Title') 11 | 12 | @yield('page_subtitle','') 13 | 14 | 15 | 16 | 17 | 18 | @yield('page_actions') 19 | 20 | 21 | 22 | @yield('page_status') 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /resources/themes/architect/views/layouts/partials/htmlheader.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | {{ config('app.name') }} - @yield('htmlheader_title','🥇 An LDAP Administration Tool') 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | @if(file_exists('css/fixes.css')) 27 | 28 | 29 | @endif 30 | 31 | @if(file_exists('css/custom.css')) 32 | 33 | 34 | @endif 35 | 36 | 37 | @yield('page-styles') 38 | {{-- 39 | @if(file_exists('css/print.css')) 40 | 41 | 42 | @endif 43 | --}} 44 | 45 | -------------------------------------------------------------------------------- /resources/themes/architect/views/layouts/partials/scripts.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 16 | 17 | @if(file_exists('js/custom.js')) 18 | 19 | 20 | @endif -------------------------------------------------------------------------------- /resources/themes/architect/views/layouts/partials/sidebarmenu.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | {{ $server->name }} 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /resources/views/components/alert/attribute_tags_cant_manage.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Unable to display this attribute as it has attribute tags [{!! $tags->join(', ') !!}]. 6 | You can manage it with an LDIF import. 7 | 8 | 9 | -------------------------------------------------------------------------------- /resources/views/components/attribute.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | @foreach($o->langtags as $langtag) 6 | $loop->index === 0]) id="langtag-{{ $o->name_lc }}-{{ $langtag }}" role="tabpanel"> 7 | @foreach(Arr::get(old($o->name_lc,[$langtag=>$new ? [NULL] : $o->tagValues($langtag)]),$langtag,[]) as $key => $value) 8 | @if($edit && (! $o->is_rdn)) 9 | 10 | ($e=$errors->get($o->name_lc.'.'.$langtag.'.'.$loop->index)),'mb-1','border-focus'=>! ($tv=$o->tagValuesOld($langtag))->contains($value),'bg-success-subtle'=>$updated]) name="{{ $o->name_lc }}[{{ $langtag }}][]" value="{{ $value }}" placeholder="{{ ! is_null($x=$tv->get($loop->index)) ? $x : '['.__('NEW').']' }}" @readonly(! $new) @disabled($o->isDynamic())> 11 | 12 | 13 | @if($e) 14 | {{ join('|',$e) }} 15 | @endif 16 | 17 | 18 | 19 | @else 20 | $updated]) value="{{ $value }}" disabled> 21 | @endif 22 | @endforeach 23 | 24 | @endforeach 25 | 26 | @if($edit && (! $o->is_rdn)) 27 | 28 | 29 | It is not possible to create new language tags at the moment. This functionality should come soon. 30 | You can create them with an LDIF import though. 31 | 32 | 33 | @endif 34 | 35 | 36 | -------------------------------------------------------------------------------- /resources/views/components/attribute/binary/jpegphoto.blade.php: -------------------------------------------------------------------------------- 1 | @use(App\Ldap\Entry) 2 | 3 | 4 | 5 | 6 | 7 | @foreach($o->tagValuesOld() as $key => $value) 8 | 9 | @switch($x=$f->buffer($value,FILEINFO_MIME_TYPE)) 10 | @case('image/jpeg') 11 | @default 12 | 13 | 14 | ($e=$errors->get($o->name_lc.'.'.Entry::TAG_NOTAG.'.'.$loop->index)),'bg-success-subtle'=>$updated]) src="data:{{ $x }};base64, {{ base64_encode($value) }}" /> 15 | 16 | @if($edit) 17 | 18 | 19 | @lang('Delete') 20 | 21 | 22 | @if($e) 23 | {{ join('|',$e) }} 24 | @endif 25 | 26 | @endif 27 | 28 | @endswitch 29 | 30 | @endforeach 31 | 32 | -------------------------------------------------------------------------------- /resources/views/components/attribute/internal.blade.php: -------------------------------------------------------------------------------- 1 | 2 | @foreach(old($o->name_lc,$o->values) as $value) 3 | @if($loop->index)@endif 4 | {{ $value }} 5 | @endforeach -------------------------------------------------------------------------------- /resources/views/components/attribute/internal/timestamp.blade.php: -------------------------------------------------------------------------------- 1 | 2 | @foreach(old($o->name_lc,$o->values) as $value) 3 | @if($loop->index)@endif 4 | {{ \Carbon\Carbon::createFromTimestamp(strtotime($value))->format(config('pla.datetime_format','Y-m-d H:i:s')) }} 5 | @endforeach -------------------------------------------------------------------------------- /resources/views/components/attribute/krblastfailedauth.blade.php: -------------------------------------------------------------------------------- 1 | 2 | @include('components.form.disabled.datetime') 3 | -------------------------------------------------------------------------------- /resources/views/components/attribute/krblastpwdchange.blade.php: -------------------------------------------------------------------------------- 1 | 2 | @include('components.form.disabled.datetime') -------------------------------------------------------------------------------- /resources/views/components/attribute/krblastsuccessfulauth.blade.php: -------------------------------------------------------------------------------- 1 | 2 | @include('components.form.disabled.datetime') -------------------------------------------------------------------------------- /resources/views/components/attribute/krbloginfailedcount.blade.php: -------------------------------------------------------------------------------- 1 | 2 | @include('components.form.disabled.input') -------------------------------------------------------------------------------- /resources/views/components/attribute/krbpasswordexpiration.blade.php: -------------------------------------------------------------------------------- 1 | 2 | @include('components.form.disabled.datetime') -------------------------------------------------------------------------------- /resources/views/components/attribute/krbprincipalkey.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | @foreach($o->langtags as $langtag) 4 | @foreach(($o->tagValues($langtag)->count() ? $o->tagValues($langtag) : [$langtag => NULL]) as $key => $value) 5 | @if($edit) 6 | 7 | ($e=$errors->get($o->name_lc.'.'.$langtag.'.'.$loop->index)),'mb-1','border-focus'=>! $o->tagValuesOld($langtag)->contains($value),'bg-success-subtle'=>$updated]) name="{{ $o->name_lc }}[{{ $langtag }}][]" value="{{ Arr::get(old($o->name_lc),$langtag.'.'.$loop->index,$value ? md5($value) : '') }}" @readonly(! $new)> 8 | 9 | 10 | @if($e) 11 | {{ join('|',$e) }} 12 | @endif 13 | 14 | 15 | @else 16 | {{ $o->render_item_old($langtag.'.'.$key) }} 17 | @endif 18 | @endforeach 19 | @endforeach 20 | -------------------------------------------------------------------------------- /resources/views/components/attribute/layout.blade.php: -------------------------------------------------------------------------------- 1 | 2 | (! $edit) && (! ($detail ?? FALSE))])> 3 | 4 | 5 | {{ $slot }} 6 | 7 | 8 | 9 | 10 | 11 | 12 | @yield($o->name_lc.'-scripts') -------------------------------------------------------------------------------- /resources/views/components/attribute/objectclass.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | @foreach($o->langtags as $langtag) 4 | @foreach(($o->tagValues($langtag)->count() ? $o->tagValues($langtag) : [$langtag => NULL]) as $key => $value) 5 | @if($edit) 6 | 7 | @else 8 | {{ $o->render_item_old($key) }} 9 | @if($o->isStructural($value)) 10 | 11 | @lang('structural') 12 | @endif 13 | 14 | @endif 15 | @endforeach 16 | @endforeach 17 | -------------------------------------------------------------------------------- /resources/views/components/attribute/password.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | @foreach($o->langtags as $langtag) 4 | @foreach(($o->tagValues($langtag)->count() ? $o->tagValues($langtag) : [$langtag => NULL]) as $key => $value) 5 | @if($edit) 6 | 7 | 8 | ($e=$errors->get($o->name_lc.'.'.$langtag.'.'.$loop->index)),'mb-1','border-focus'=>! $o->tagValuesOld($langtag)->contains($value),'bg-success-subtle'=>$updated]) name="{{ $o->name_lc }}[{{ $langtag }}][]" value="{{ Arr::get(old($o->name_lc),$langtag.'.'.$loop->index,$value ? md5($value) : '') }}" @readonly(! $new)> 9 | 10 | 11 | @if($e) 12 | {{ join('|',$e) }} 13 | @endif 14 | 15 | 16 | @else 17 | {{ $o->render_item_old($langtag.'.'.$key) }} 18 | @endif 19 | @endforeach 20 | @endforeach 21 | 22 | 23 | @if($edit) 24 | 25 | 26 | 27 | @lang('Check Password') 28 | 29 | 30 | 31 | @endif -------------------------------------------------------------------------------- /resources/views/components/attribute/schema/generic.blade.php: -------------------------------------------------------------------------------- 1 | {!! $o->values->join('') !!} -------------------------------------------------------------------------------- /resources/views/components/attribute/schema/mechanisms.blade.php: -------------------------------------------------------------------------------- 1 | {!! $o->values 2 | ->transform(function($item) use ($o) { 3 | return sprintf('%s%s%s', 4 | $item, 5 | $o->get($item,'title'), 6 | ($x=$o->get($item,'ref')) ? sprintf('',$x) : '', 7 | $o->get($item,'desc'), 8 | ); 9 | })->join('') !!} -------------------------------------------------------------------------------- /resources/views/components/attribute/schema/oid.blade.php: -------------------------------------------------------------------------------- 1 | {!! $o->values 2 | ->transform(function($item) use ($o) { 3 | return preg_match('/[0-9]+\.[0-9]+\.[0-9]+/',$item) 4 | ? sprintf('%s%s%s', 5 | $item, 6 | $o->get($item,'title'), 7 | ($x=$o->get($item,'ref')) ? sprintf('',$x) : '', 8 | $o->get($item,'desc'), 9 | ) 10 | : $item; 11 | })->join('') !!} -------------------------------------------------------------------------------- /resources/views/components/attribute/widget/objectclass.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ($e=$errors->get($o->name_lc.'.'.$langtag.'.'.$loop->index)),'mb-1','border-focus'=>! $o->tagValuesOld($langtag)->contains($value),'bg-success-subtle'=>$updated]) name="{{ $o->name_lc }}[{{ $langtag }}][]" value="{{ $value }}" placeholder="{{ Arr::get($o->values,$loop->index,'['.__('NEW').']') }}" @readonly(true)> 5 | @if($o->isStructural($value)) 6 | @lang('structural') 7 | @else 8 | 9 | @endif 10 | 11 | @if($e) 12 | {{ join('|',$e) }} 13 | @endif 14 | 15 | 16 | -------------------------------------------------------------------------------- /resources/views/components/error.blade.php: -------------------------------------------------------------------------------- 1 | @if($errors->any()) 2 | 3 | @lang('Validation Errors') 4 | 5 | @endif -------------------------------------------------------------------------------- /resources/views/components/failed.blade.php: -------------------------------------------------------------------------------- 1 | @if(session()->has('failed')) 2 | 3 | {{ session()->pull('failed') }} 4 | 5 | @endif -------------------------------------------------------------------------------- /resources/views/components/file-note.blade.php: -------------------------------------------------------------------------------- 1 | @if(file_exists($file)) 2 | 3 | 4 | 5 | NOTE 6 | 7 | {!! file_get_contents($file) !!} 8 | 9 | 10 | 11 | 12 | @endif -------------------------------------------------------------------------------- /resources/views/components/form/base.blade.php: -------------------------------------------------------------------------------- 1 | 2 | @if(isset($label)) 3 | only(['class'])->merge(['class'=>'form-label']) }} for="{{ $id ?? $name }}">{!! html_entity_decode($label) !!} 4 | @endisset 5 | 6 | @if(isset($icon) || isset($prepend)) 7 | {{-- // messes with the icon box, we have rounded corners on the right side 8 | 9 | --}} 10 | @isset($icon)@endisset @isset($prepend){!! $prepend !!}@endisset 11 | {{-- 12 | 13 | --}} 14 | @endif 15 | {{ $slot }} 16 | @isset($name) 17 | 18 | @error((! empty($old)) ? $old : ($id ?? $name)) 19 | {{ $message }} 20 | @elseif(isset($feedback)) 21 | {{ $feedback }} 22 | @enderror 23 | 24 | @endisset 25 | 26 | @isset($helper) 27 | {!! html_entity_decode($helper) !!} 28 | @endif 29 | -------------------------------------------------------------------------------- /resources/views/components/form/cancel.blade.php: -------------------------------------------------------------------------------- 1 | Cancel 2 | 3 | @section('page-scripts') 4 | 9 | @append -------------------------------------------------------------------------------- /resources/views/components/form/disabled/datetime.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | @foreach($o->langtags as $langtag) 4 | @foreach(Arr::get(old($o->name_lc,[$langtag=>$o->tagValues($langtag)]),$langtag,[]) as $value) 5 | 6 | 7 | 8 | @endforeach 9 | @endforeach 10 | -------------------------------------------------------------------------------- /resources/views/components/form/disabled/input.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | @foreach($o->langtags as $langtag) 4 | @foreach(Arr::get(old($o->name_lc,[$langtag=>$o->tagValues($langtag)]),$langtag,[]) as $value) 5 | 6 | 7 | 8 | @endforeach 9 | @endforeach 10 | -------------------------------------------------------------------------------- /resources/views/components/form/reset.blade.php: -------------------------------------------------------------------------------- 1 | @lang('Reset') 2 | 3 | @section('page-scripts') 4 | 9 | @append -------------------------------------------------------------------------------- /resources/views/components/form/submit.blade.php: -------------------------------------------------------------------------------- 1 | @lang($action) 2 | 3 | @section('page-scripts') 4 | 9 | @append -------------------------------------------------------------------------------- /resources/views/components/modal/close.blade.php: -------------------------------------------------------------------------------- 1 | @lang('Close') -------------------------------------------------------------------------------- /resources/views/components/note.blade.php: -------------------------------------------------------------------------------- 1 | @if(session()->has('note')) 2 | 3 | {{ session()->pull('note') }} 4 | 5 | @endif -------------------------------------------------------------------------------- /resources/views/components/success.blade.php: -------------------------------------------------------------------------------- 1 | @if(session()->has('success')) 2 | 3 | Success! 4 | 5 | 6 | @foreach(session()->get('success') as $item) 7 | {{ $item }} 8 | @endforeach 9 | 10 | 11 | @endif -------------------------------------------------------------------------------- /resources/views/components/syntax/certificate.blade.php: -------------------------------------------------------------------------------- 1 | @use(App\Classes\LDAP\Attribute\Certificate) 2 | 3 | 4 | 5 | @foreach($o->tagValuesOld('binary') as $key => $value) 6 | 7 | @if(($o instanceof Certificate) && $edit) 8 | 9 | 10 | 11 | certificate())) }}" disabled>{{ $x }} 12 | 13 | 14 | @if($e=$errors->get($o->name_lc.'.binary.'.$loop->index)) 15 | {{ join('|',$e) }} 16 | @endif 17 | 18 | 19 | 20 | @lang('Certificate Subject'): {{ $o->subject($loop->index) }} 21 | {{ ($expire=$o->expires($loop->index))->isPast() ? __('Expired') : __('Expires') }}: {{ $expire->format(config('pla.datetime_format','Y-m-d H:i:s')) }} 22 | 23 | 24 | @else 25 | {{ $o->render_item_old('binary.'.$key) }} 26 | @endif 27 | @endforeach 28 | -------------------------------------------------------------------------------- /resources/views/components/syntax/certificatelist.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | @foreach($o->tagValuesOld('binary') as $key => $value) 4 | 5 | {{ $o->render_item_old('binary.'.$key) }} 6 | @endforeach 7 | -------------------------------------------------------------------------------- /resources/views/components/updated.blade.php: -------------------------------------------------------------------------------- 1 | @if(session()->has('updated')) 2 | 3 | @lang('Entry updated') [{{ session()->get('updated')->count() }} @lang('attributes(s)')] 4 | 5 | @endif -------------------------------------------------------------------------------- /resources/views/debug.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | DEBUG Information 6 | 7 | 8 | 9 | 10 | Setting 11 | Value 12 | 13 | 14 | 15 | 16 | 17 | 18 | User 19 | {{ $user }} 20 | 21 | 22 | 23 | 24 | BaseDN(s) 25 | 26 | 27 | @foreach($server->baseDNs(TRUE)->sort(fn($item)=>$item->sort_key) as $item) 28 | 29 | {{ $item->getDn() }} 30 | 31 | @endforeach 32 | 33 | 34 | 35 | 36 | 37 | 38 | Schema DN 39 | {{ $server->schemaDN() }} 40 | 41 | 42 | 43 | 44 | Root URL 45 | {{ request()->root() }} 46 | 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /resources/views/errors/401.blade.php: -------------------------------------------------------------------------------- 1 | @extends('architect::layouts.error') 2 | 3 | @section('error') 4 | 401: @lang('LDAP Authentication Error') 5 | @endsection 6 | 7 | @section('content') 8 | {{ $exception->getMessage() }} 9 | @endsection -------------------------------------------------------------------------------- /resources/views/errors/555.blade.php: -------------------------------------------------------------------------------- 1 | @extends('architect::layouts.error') 2 | 3 | @section('title') 4 | @lang('Not Implemented') (555) 5 | @endsection 6 | 7 | @section('content') 8 | {{ $exception->getMessage() }} 9 | @endsection -------------------------------------------------------------------------------- /resources/views/errors/597.blade.php: -------------------------------------------------------------------------------- 1 | @extends('architect::layouts.error') 2 | 3 | @section('error') 4 | 597: @lang('LDAP Server Unavailable') 5 | @endsection 6 | 7 | @section('content') 8 | @switch($exception->getMessage()) 9 | @case("Can't contact LDAP server") 10 | 11 | 12 | @lang('Error') 13 | 14 | 15 | 16 | {{ $exception->getMessage() }} 17 | 18 | 19 | 20 | @lang('Possible Causes') 21 | 22 | 23 | 24 | 25 | @lang('Your LDAP server is not connectable') 26 | @lang('Your LDAP server hostname is incorrect') 27 | @lang('Your DNS server cannot resolve that hostname') 28 | @lang('Your Resolver is not pointing to your DNS server') 29 | 30 | 31 | 32 | 33 | @break 34 | 35 | @default 36 | {{ $exception->getMessage() }} 37 | @endswitch 38 | @endsection -------------------------------------------------------------------------------- /resources/views/errors/598.blade.php: -------------------------------------------------------------------------------- 1 | @extends('architect::layouts.error') 2 | 3 | @section('title') 4 | @lang('Error') (598) 5 | @endsection 6 | 7 | @section('content') 8 | {{ $exception->getMessage() }} 9 | @endsection -------------------------------------------------------------------------------- /resources/views/errors/599.blade.php: -------------------------------------------------------------------------------- 1 | @extends('architect::layouts.error') 2 | 3 | @section('title') 4 | 599: @lang('Untrapped Error') 5 | @endsection 6 | 7 | @section('content') 8 | {{ $exception->getMessage() }} 9 | @endsection -------------------------------------------------------------------------------- /resources/views/fragment/dn/add_attr.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Add New Attribute 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /resources/views/fragment/dn/header.blade.php: -------------------------------------------------------------------------------- 1 | @use(App\Ldap\Entry) 2 | 3 | 4 | 5 | 6 | {!! ($x=$o->getObject('jpegphoto')) ? $x->render(FALSE,TRUE) : sprintf('',$o->icon() ?? "fas fa-info") !!} 7 | 8 | {{ $o->getDn() }} 9 | 10 | 11 | 12 | 13 | 14 | Created 15 | 16 | [] 17 | 18 | 19 | 20 | Modified 21 | 22 | [] 23 | 24 | 25 | 26 | UUID 27 | 28 | 29 | 30 | 31 | 32 | @if(($x=$o->getLangTags() 33 | ->flatMap(fn($item)=>$item->values()) 34 | ->unique() 35 | ->sort() 36 | ->filter(fn($item)=>($item !== Entry::TAG_NOTAG)) 37 | ->map(fn($item)=>preg_replace('/'.Entry::LANG_TAG_PREFIX.'/','',$item))) 38 | ->count()) 39 | 40 | Tags 41 | {{ $x->join(', ') }} 42 | 43 | @endif 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /resources/views/fragment/export.blade.php: -------------------------------------------------------------------------------- 1 | 2 | {{ $result }} 3 | -------------------------------------------------------------------------------- /resources/views/fragment/schema/ldapsyntaxes.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | @lang('Description') 7 | OID 8 | 9 | 10 | 11 | 12 | @foreach($ldapsyntaxes as $o) 13 | 14 | 15 | {{ $o->description }} 16 | @if($o->binary_transfer_required) 17 | 18 | @endif 19 | @if($o->is_not_human_readable) 20 | 21 | @endif 22 | 23 | {{ $o->oid }} 24 | 25 | @endforeach 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /resources/views/frame.blade.php: -------------------------------------------------------------------------------- 1 | @extends('architect::layouts.app') 2 | 3 | @section('main-content') 4 | @include('frames.'.$subframe) 5 | @endsection 6 | 7 | @section('page-scripts') 8 | 11 | @append -------------------------------------------------------------------------------- /resources/views/frames/import_result.blade.php: -------------------------------------------------------------------------------- 1 | @section('page_title') 2 | 3 | 4 | 5 | @lang('LDIF Import Result')@lang('To Server') {{ $server->name }} 6 | 7 | 8 | @endsection 9 | 10 | @section('main-content') 11 | 12 | 13 | 14 | 15 | 16 | 17 | @lang('Import Result') 18 | @lang('LDIF') 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | @lang('DN') 27 | @lang('Result') 28 | @lang('Line') 29 | 30 | 31 | @foreach($result as $item) 32 | 33 | {{ $item->get('dn') }} 34 | {{ $item->get('result') }} 35 | {{ $item->get('line') }} 36 | 37 | @endforeach 38 | 39 | 40 | 41 | 42 | {{ $ldif }} 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | @endsection 51 | 52 | @section('page-scripts') 53 | 60 | @append -------------------------------------------------------------------------------- /resources/views/frames/info.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.dn') 2 | 3 | @section('page_title') 4 | 5 | 6 | 7 | @lang('Server Info'){{ $server->rootDSE()->entryuuid[0] ?? '' }} 8 | 9 | 10 | @endsection 11 | 12 | @section('main-content') 13 | 14 | 15 | 16 | @foreach($server->rootDSE()->getObjects() as $attribute => $ao) 17 | 18 | 19 | {!! ($x=$server->schema('attributetypes',$attribute)) 20 | ? sprintf('%s',$x->name_lc,url('schema/attributetypes',$x->name_lc),$x->name) 21 | : $attribute !!} 22 | 23 | 24 | 25 | 26 | 27 | @endforeach 28 | 29 | 30 | 31 | @endsection -------------------------------------------------------------------------------- /resources/views/layouts/dn.blade.php: -------------------------------------------------------------------------------- 1 | @if(trim($__env->yieldContent('page_title'))) 2 | @include('architect::layouts.partials.contentheader') 3 | @endif 4 | 5 | 6 | 7 | 8 | 9 | @yield('main-content') 10 | 11 | 12 | 13 | @yield('page-modals') 14 | @yield('page-scripts') 15 | @yield('page-styles') 16 | 17 | 18 | -------------------------------------------------------------------------------- /resources/views/modals/entry-delete.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | @lang('WARNING'): @lang('Delete') {{ Crypt::decryptString($dn) }} 4 | 5 | 6 | 7 | 8 | 9 | @lang('Deleting this DN will permanently delete it from your LDAP server.') 10 | 11 | 12 | 16 | 17 | 18 | @csrf 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /resources/views/modals/entry-export.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | LDIF for {{ Crypt::decryptString($dn) }} 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 15 | 16 | -------------------------------------------------------------------------------- /storage/app/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !public/ 3 | !.gitignore 4 | -------------------------------------------------------------------------------- /storage/app/public/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/framework/.gitignore: -------------------------------------------------------------------------------- 1 | config.php 2 | routes.php 3 | schedule-* 4 | compiled.php 5 | services.json 6 | events.scanned.php 7 | routes.scanned.php 8 | down 9 | -------------------------------------------------------------------------------- /storage/framework/cache/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !data/ 3 | !.gitignore 4 | -------------------------------------------------------------------------------- /storage/framework/cache/data/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/framework/sessions/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/framework/testing/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/framework/views/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/logs/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /tests/CreatesApplication.php: -------------------------------------------------------------------------------- 1 | make(Kernel::class)->bootstrap(); 19 | 20 | return $app; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /tests/Feature/ExampleTest.php: -------------------------------------------------------------------------------- 1 | get('/login'); 16 | 17 | $response->assertStatus(200); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /tests/Feature/GetBaseDNTest.php: -------------------------------------------------------------------------------- 1 | assertIsObject($o); 22 | $this->assertCount(6,$o->toArray()); 23 | $this->assertEquals('c=AU',$o->first()->getDn()); 24 | } 25 | } -------------------------------------------------------------------------------- /tests/Feature/ImportTest.php: -------------------------------------------------------------------------------- 1 | assertTrue($this->login()); 18 | $this->assertTrue(Auth::check()); 19 | $this->actingAs(Auth::user()); 20 | $this->assertFalse(config('ldap.cache.enabled')); 21 | 22 | // Check that it exists 23 | $this->assertEquals($dn,$x=config('server')->fetch($dn)); 24 | $this->assertTrue($x->exists); 25 | 26 | // Delete the entry 27 | $x->delete(); 28 | $this->assertEquals(NULL,config('server')->fetch($dn)); 29 | 30 | $file = new UploadedFile($import_file,'ldif-import.ldif',null,null,true); 31 | 32 | $response = $this 33 | ->actingAs(Auth::user()) 34 | ->from('/import') 35 | ->post('/import/process/ldif',[ 36 | '_token' => csrf_token(), 37 | 'key'=>Crypt::encryptString('*import|_NOP'), 38 | 'file' => $file, 39 | ]); 40 | 41 | //$response->dump(); 42 | $response->assertSuccessful(); 43 | 44 | // Check that it hsa been created 45 | $this->assertEquals($dn,$x=config('server')->fetch($dn)); 46 | $this->assertTrue($x->exists); 47 | } 48 | } -------------------------------------------------------------------------------- /tests/Feature/LoginTest.php: -------------------------------------------------------------------------------- 1 | get('/login'); 14 | 15 | $response->assertSuccessful(); 16 | $response->assertViewIs('architect::auth.login'); 17 | } 18 | 19 | public function test_admin_dn_login() 20 | { 21 | $this->assertTrue($this->login()); 22 | $this->assertTrue(Auth::check()); 23 | 24 | $this->assertTrue(Session::has('username_encrypt')); 25 | $this->assertTrue(Session::has('password_encrypt')); 26 | } 27 | } -------------------------------------------------------------------------------- /tests/TestCase.php: -------------------------------------------------------------------------------- 1 | instance('config', $config); 30 | app()->instance('events', $events); 31 | } 32 | 33 | protected function login(): bool 34 | { 35 | //$username = 'cn=AdminUser,dc=Test'; 36 | $username = 'admin'; 37 | $password = 'password'; 38 | 39 | $this->post('/login',['uid'=>$username,'password'=>$password]); 40 | 41 | return Auth::check() && (Auth::user()->getDN() === 'cn=AdminUser,dc=Test'); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /tests/Unit/ExampleTest.php: -------------------------------------------------------------------------------- 1 | assertTrue(true); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /tests/server/openldap/bases/21-example.com.ldif: -------------------------------------------------------------------------------- 1 | dn: olcDatabase=mdb,cn=config 2 | objectClass: olcDatabaseConfig 3 | objectClass: olcMdbConfig 4 | olcDbDirectory: /var/lib/openldap/data 5 | olcDatabase: mdb 6 | olcLastMod: TRUE 7 | olcMonitoring: TRUE 8 | olcSuffix: dc=example,dc=com 9 | olcAccess: to dn.base="" by dn="cn=admin,dc=Test" write by * read 10 | olcAccess: to * by dn="cn=admin,dc=example,dc=com" write by dn="cn=admin,dc=Test" write by * read 11 | olcRootDN: cn=admin,dc=example,dc=com 12 | olcRootPW: {SSHA}e8xGdXmL+mSD3u/389YHeM+dpqFCUSyq 13 | -------------------------------------------------------------------------------- /tests/server/openldap/bases/22-example_com.ldif: -------------------------------------------------------------------------------- 1 | dn: olcDatabase=mdb,cn=config 2 | objectClass: olcDatabaseConfig 3 | objectClass: olcMdbConfig 4 | olcDbDirectory: /var/lib/openldap/data 5 | olcDatabase: mdb 6 | olcLastMod: TRUE 7 | olcMonitoring: TRUE 8 | olcSuffix: dc=example.com 9 | olcAccess: to dn.base="" by dn="cn=admin,dc=Test" write by * read 10 | olcAccess: to * by dn="cn=AdminUser,dc=Test" write by anonymous write by * write 11 | olcRootDN: cn=admin,dc=example.com 12 | olcRootPW: {SSHA}e8xGdXmL+mSD3u/389YHeM+dpqFCUSyq 13 | -------------------------------------------------------------------------------- /tests/server/openldap/bases/23-flintstones.ldif: -------------------------------------------------------------------------------- 1 | dn: olcDatabase=mdb,cn=config 2 | objectClass: olcDatabaseConfig 3 | objectClass: olcMdbConfig 4 | olcDbDirectory: /var/lib/openldap/data 5 | olcDatabase: mdb 6 | olcLastMod: TRUE 7 | olcMonitoring: TRUE 8 | olcSuffix: o=Flintstones 9 | olcAccess: to dn.base="" by dn="cn=admin,dc=Test" write by * read 10 | olcAccess: to * by dn="cn=admin,o=Flintstones" write by dn="cn=admin,dc=Test" write by * read 11 | olcRootDN: cn=admin,o=Flintstones 12 | olcRootPW: {SSHA}e8xGdXmL+mSD3u/389YHeM+dpqFCUSyq 13 | -------------------------------------------------------------------------------- /tests/server/openldap/bases/24-simpsons.ldif: -------------------------------------------------------------------------------- 1 | dn: olcDatabase=mdb,cn=config 2 | objectClass: olcDatabaseConfig 3 | objectClass: olcMdbConfig 4 | olcDbDirectory: /var/lib/openldap/data 5 | olcDatabase: mdb 6 | olcLastMod: TRUE 7 | olcMonitoring: TRUE 8 | olcSuffix: o=Simpsons 9 | olcAccess: to dn.base="" by dn="cn=admin,dc=Test" write by * read 10 | #olcAccess: to attrs=userPassword,shadowLastChange by dn="cn=admin,dc=Test" write by anonymous auth by self =xw by * none 11 | olcAccess: to attrs=userPassword,shadowLastChange by dn="cn=admin,dc=Test" write by anonymous auth by self write by * none 12 | olcAccess: to * by dn="cn=admin,o=Simpsons" write by dn="cn=admin,dc=Test" write by * read 13 | olcRootDN: cn=admin,o=Simpsons 14 | olcRootPW: {SSHA}e8xGdXmL+mSD3u/389YHeM+dpqFCUSyq 15 | -------------------------------------------------------------------------------- /tests/server/openldap/bases/25-test.ldif: -------------------------------------------------------------------------------- 1 | dn: olcDatabase=mdb,cn=config 2 | objectClass: olcDatabaseConfig 3 | objectClass: olcMdbConfig 4 | olcDbDirectory: /var/lib/openldap/data 5 | olcDatabase: mdb 6 | olcLastMod: TRUE 7 | olcMonitoring: TRUE 8 | olcSuffix: dc=Test 9 | olcAccess: to dn.base="" by dn="cn=admin,dc=Test" write by * read 10 | olcAccess: to * by dn="cn=admin,dc=Test" write by dn="cn=admin,dc=Test" write by * read 11 | olcRootDN: cn=admin,dc=Test 12 | olcRootPW: {SSHA}UCTtlcHOSqGCFuKtOCJAU8k8icNpVGiw 13 | -------------------------------------------------------------------------------- /tests/server/openldap/data/01-au.ldif: -------------------------------------------------------------------------------- 1 | # Base DN 2 | dn: c=AU 3 | c: AU 4 | objectclass: country 5 | -------------------------------------------------------------------------------- /tests/server/openldap/data/04-example_com.ldif: -------------------------------------------------------------------------------- 1 | # LDIF Export for dc=example.com 2 | 3 | #version: 1 4 | 5 | # Entry 1: dc=example.com 6 | dn: dc=example.com 7 | dc: example.com 8 | objectclass: dNSDomain 9 | 10 | # Entry 2: cn=group,dc=example.com 11 | dn: cn=group,dc=example.com 12 | cn: group 13 | gidnumber: 100 14 | objectclass: posixGroup 15 | objectclass: top 16 | 17 | -------------------------------------------------------------------------------- /tests/server/openldap/data/04-z_kerberos.ldif: -------------------------------------------------------------------------------- 1 | dn: cn=kerberos,dc=example.com 2 | cn: kerberos 3 | uid: kerberos 4 | gidNumber: 1999 5 | uidNumber: 1999 6 | homeDirectory: /home/kerberos 7 | krbextradata: blahblahblah 8 | krbextradata: blahblah 9 | krbextradata: blah 10 | krblastfailedauth: 20230214150806Z 11 | krblastpwdchange: 20161127174314Z 12 | krblastsuccessfulauth: 20230303125823Z 13 | krbloginfailedcount: 0 14 | krbmaxrenewableage: 604800 15 | krbmaxticketlife: 86400 16 | krbobjectreferences: uid=kerberos,dc=example.com 17 | krbpasswordexpiration: 19700101000000Z 18 | krbprincipalkey: SooperSekretString 19 | krbprincipalname: kerberos@test 20 | krbpwdpolicyreference: cn=AccountLockout,dc=example.com 21 | krbticketflags: 4224 22 | objectclass: posixAccount 23 | objectclass: krbPrincipal 24 | objectclass: krbPrincipalAux 25 | objectclass: krbTicketPolicyAux 26 | objectclass: top 27 | -------------------------------------------------------------------------------- /tests/server/openldap/data/04-z_labeleduri.ldif: -------------------------------------------------------------------------------- 1 | 2 | dn: cn=tech_staff,dc=example.com 3 | cn: tech_staff 4 | labeleduri: ldap:///dc=example.com?uid?one?(|(cn=kerberos)(uidNumber=*)) 5 | objectclass: nisMailAlias 6 | objectclass: labeledURIObject 7 | -------------------------------------------------------------------------------- /tests/server/openldap/data/04-z_usercert.ldif: -------------------------------------------------------------------------------- 1 | 2 | dn: uid=usercert,dc=example.com 3 | cn: cn 4 | gidNumber: 1111 5 | homeDirectory: /home 6 | objectClass: account 7 | objectClass: posixAccount 8 | objectClass: pkiUser 9 | uid: usercert 10 | uidNumber: 111 11 | usercertificate;binary:: MIIC2TCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQQFADBGMQswCQYD 12 | VQQGEwJJVDENMAsGA1UEChMESU5GTjESMBAGA1UECxMJQXV0aG9yaXR5MRQwEgYDVQQDEwtJTkZO 13 | IENBICgyKTAeFw05OTA2MjMxMTE2MDdaFw0wMzA4MDExMTE2MDdaMEYxCzAJBgNVBAYTAklUMQ0w 14 | CwYDVQQKEwRJTkZOMRIwEAYDVQQLEwlBdXRob3JpdHkxFDASBgNVBAMTC0lORk4gQ0EgKDIpMIGf 15 | MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrHdRKJsobcjXz/OsGjyq8v73DbggG3JCGrQZ9f1Vm 16 | 9RrIWJPwggczqgxwWL6JLPKglxbUjAtUxiZm3fw2kX7FGMUq5JaN/Pk2PT4ExA7bYLnbLGZ9jKJs 17 | Dh4bNOKrGRIxRO9Ff+YwmH8EQdoVpSRFbBpNnoDIkHLc4DtzB+B4wwIDAQABo4HWMIHTMAwGA1Ud 18 | EwQFMAMBAf8wHQYDVR0OBBYEFK3QjOXGc4j9LqYEYTn9WvSRAcusMG4GA1UdIwRnMGWAFK3QjOXG 19 | c4j9LqYEYTn9WvSRAcusoUqkSDBGMQswCQYDVQQGEwJJVDENMAsGA1UEChMESU5GTjESMBAGA1UE 20 | CxMJQXV0aG9yaXR5MRQwEgYDVQQDEwtJTkZOIENBICgyKYIBADALBgNVHQ8EBAMCAQYwEQYJYIZI 21 | AYb4QgEBBAQDAgAHMAkGA1UdEQQCMAAwCQYDVR0SBAIwADANBgkqhkiG9w0BAQQFAAOBgQCDs5b1 22 | jmbIYVq2epd5iDjQ109SJ/V7b6DFw2NIl8CWeDPOOjL1E5M8dnlmCDeTR2TlBxqUZaBBJZPqzFdv 23 | xpxqsHC0HfkCXAnUe5MaefFNAH9WbxoB/A2pkXtT6WGWed+QsL5wyKJaO4oD9UD5T+x12aGsHcsD 24 | Cy3EVEaGEOl+/A== 25 | -------------------------------------------------------------------------------- /tests/server/openldap/data/07-test-il8n.ldif: -------------------------------------------------------------------------------- 1 | # This is a Test-File for characters / encoding 2 | # 1. Change the 3 | # ,dc=Test 4 | # to avalue for your organisation 5 | # 2. Import it with phpldapadmin 6 | # 7 | # pla-i18n, example.com 8 | # 9 | dn: ou=pla-i18n,dc=Test 10 | ou: pla-i18n 11 | objectClass: top 12 | objectClass: organizationalUnit 13 | 14 | # pl, pla-i18n, example.com 15 | dn: ou=pl,ou=pla-i18n,dc=Test 16 | description:: IGRvcMOza2k= 17 | description:: xITFu8WaxbnEhsWDxYHDk8SYIMSFxbzFm8W6xIfFhMWCw7PEmQ== 18 | description:: V3NrYXrDs3drYQ== 19 | objectClass: top 20 | objectClass: organizationalUnit 21 | ou: pl 22 | 23 | # ru, pla-i18n, example.com 24 | dn: ou=ru,ou=pla-i18n,dc=Test 25 | description:: 0LfQstGD0YfQuNGCINC/0L7QtNC+0LHQvdC+ 26 | description:: 0J/RgNC+0YHRgtCw0Y8g0YTQvtGA0LzQsCDQv9C+0LjRgdC6 27 | objectClass: top 28 | objectClass: organizationalUnit 29 | ou: ru 30 | 31 | # jp, pla-i18n, example.com 32 | dn: ou=jp,ou=pla-i18n,dc=Test 33 | ou: jp 34 | objectClass: top 35 | objectClass: organizationalUnit 36 | description:: SVNPLTIwMjItSlDjga7lpJrlm73nsY3oqIDoqp7jgbjjga7mi6HlvLXmgKc= 37 | 38 | # pt-br, pla-i18n, example.com 39 | dn: ou=pt-br,ou=pla-i18n,dc=Test 40 | ou: pt-br 41 | objectClass: top 42 | objectClass: organizationalUnit 43 | description:: VmVyIGFzIHJlcXVpc2nDp8O1ZXMgZW0gYWJlcnRv 44 | 45 | # de, pla-i18n, example.com 46 | dn: ou=de,ou=pla-i18n,dc=Test 47 | ou: de 48 | objectClass: top 49 | objectClass: organizationalUnit 50 | description:: U29uZGVyemVpY2hlbiDDtsOkw7zDnyDDlsOEw5w= 51 | description:: w5bDliDDnMOcIMOEw4Q= 52 | 53 | # sv, pla-i18n, example.com 54 | dn: ou=sv,ou=pla-i18n,dc=Test 55 | ou: sv 56 | objectClass: top 57 | objectClass: organizationalUnit 58 | description:: U8O2a29tZsOlbmc= 59 | description:: bMOldGVyIHNvbQ== 60 | 61 | # ca, pla-i18n, example.com 62 | dn: ou=ca,ou=pla-i18n,dc=Test 63 | ou: ca 64 | objectClass: top 65 | objectClass: organizationalUnit 66 | description:: RXMgdGluZHLDoSBxdWUgY29uZmlybWFyIGFxdWVzdGEgZGVjaXNpw7M= 67 | -------------------------------------------------------------------------------- /tests/server/openldap/data/07-test.ldif: -------------------------------------------------------------------------------- 1 | # LDIF Export for dc=Test 2 | 3 | #version: 1 4 | 5 | # This entry already exists as a result of configuring the LDAP server 6 | dn: dc=Test 7 | dc: Test 8 | objectclass: dNSDomain 9 | 10 | dn: cn=AdminUser,dc=Test 11 | cn: Admin User 12 | givenname: Admin 13 | mail: admin@test 14 | objectclass: posixAccount 15 | objectclass: inetOrgPerson 16 | objectclass: top 17 | sn: User 18 | uid: admin 19 | uidNumber: 0 20 | gidNumber: 0 21 | homeDirectory: /home/admin 22 | userpassword: password 23 | -------------------------------------------------------------------------------- /tests/server/openldap/schema/add/30-uidpool.ldif: -------------------------------------------------------------------------------- 1 | ## 2 | ## Used for storing the next gid and next uid in the the directory 3 | ## 4 | dn: cn=uidpool,cn=schema,cn=config 5 | objectClass: olcSchemaConfig 6 | cn: uidpool 7 | olcObjectClasses: {0}( 1.3.6.1.4.1.7165.1.2.2.3 NAME 'uidPool' SUP top AUXILIARY 8 | DESC 'Pool for allocating UNIX uids' 9 | MUST ( uidNumber $ cn ) ) 10 | olcObjectClasses: {1}( 1.3.6.1.4.1.7165.1.2.2.4 NAME 'gidPool' SUP top AUXILIARY 11 | DESC 'Pool for allocating UNIX gids' 12 | MUST ( gidNumber $ cn ) ) 13 | -------------------------------------------------------------------------------- /tests/server/openldap/schema/modify/00-config.ldif: -------------------------------------------------------------------------------- 1 | dn: olcDatabase={0}config,cn=config 2 | changetype: modify 3 | add: olcRootPW 4 | olcRootPW:: c2VjcmV0 5 | 6 | add: olcRootDN 7 | olcRootDN: cn=config 8 | -------------------------------------------------------------------------------- /tests/server/openldap/schema/modify/00-mapsize.ldif: -------------------------------------------------------------------------------- 1 | dn: olcDatabase={3}mdb,cn=config 2 | changetype: modify 3 | add: olcDbMaxSize 4 | olcDbMaxSize: 1073741824 5 | 6 | dn: olcDatabase={4}mdb,cn=config 7 | changetype: modify 8 | add: olcDbMaxSize 9 | olcDbMaxSize: 1073741824 10 | 11 | dn: olcDatabase={5}mdb,cn=config 12 | changetype: modify 13 | add: olcDbMaxSize 14 | olcDbMaxSize: 1073741824 15 | 16 | dn: olcDatabase={6}mdb,cn=config 17 | changetype: modify 18 | add: olcDbMaxSize 19 | olcDbMaxSize: 1073741824 20 | 21 | dn: olcDatabase={7}mdb,cn=config 22 | changetype: modify 23 | add: olcDbMaxSize 24 | olcDbMaxSize: 1073741824 25 | 26 | -------------------------------------------------------------------------------- /tests/server/openldap/schema/modify/00-sizelimit.ldif: -------------------------------------------------------------------------------- 1 | dn: olcDatabase={4}mdb,cn=config 2 | changetype: modify 3 | add: olcSizeLimit 4 | olcSizeLimit: 2000 5 | -------------------------------------------------------------------------------- /tests/server/openldap/schema/modify/40-dynlist-options.ldif: -------------------------------------------------------------------------------- 1 | dn: olcOverlay=dynlist,olcDatabase={4}mdb,cn=config 2 | changetype: add 3 | objectClass: olcOverlayConfig 4 | objectClass: olcDynListConfig 5 | olcOverlay: dynlist 6 | olcDynListAttrSet: nisMailAlias labeledURI 7 | #olcDynListAttrSet: groupOfURLs memberURL memberOf 8 | #olcDynListAttrSet: groupOfURLs memberURL member+dgMemberOf 9 | #olcDynListAttrSet: groupOfURLs memberURL member 10 | #olcDynListAttrSet: groupOfURLs memberURL member 11 | #olcDynListAttrSet: groupOfURLs labeledURI member 12 | -------------------------------------------------------------------------------- /tests/server/openldap/schema/modify/99-argon.ldif: -------------------------------------------------------------------------------- 1 | dn: cn=z-module{0},cn=config 2 | changetype: modify 3 | add: olcModuleLoad 4 | olcModuleLoad: argon2 5 | -------------------------------------------------------------------------------- /webpack.mix.js: -------------------------------------------------------------------------------- 1 | const mix = require('laravel-mix'); 2 | 3 | const webpack = require('webpack') 4 | 5 | /* 6 | |-------------------------------------------------------------------------- 7 | | Mix Asset Management 8 | |-------------------------------------------------------------------------- 9 | | 10 | | Mix provides a clean, fluent API for defining some Webpack build steps 11 | | for your Laravel application. By default, we are compiling the Sass 12 | | file for the application as well as bundling up all the JS files. 13 | | 14 | */ 15 | 16 | mix.js([ 17 | 'resources/js/app.js', 18 | 'resources/js/bootstrap3-typeahead.js', 19 | 'resources/themes/architect/src/init.js' 20 | ],'public/js').extract() 21 | .sass('resources/sass/app.scss','public/css'); 22 | --------------------------------------------------------------------------------
%s
@lang('Validation Errors')
{{ session()->pull('failed') }}
{{ session()->pull('note') }}
{{ $o->render_item_old('binary.'.$key) }}
@lang('Entry updated') [{{ session()->get('updated')->count() }} @lang('attributes(s)')]
2 | {{ $result }} 3 |
{{ $ldif }}