Files
ADconsle/docs/development.md
T
kzbkowskiandClaude Sonnet 5 b313c126ce
CI / PHP 8.2 (push) Failing after 1m40s
CI / PHP 8.3 (push) Failing after 55s
CI / PHP 8.4 (push) Failing after 1m11s
Release image / image (push) Successful in 2m33s
ADconsole v1.1.0
Config backup, a Docker dev/prod split, and a Gitea-built release image.

Added
- /settings -> General -> "Configuration backup": JSON export/import of the
  panel's general settings + attribute definitions
  (App\Services\ConfigBackupService); audited as config.export / config.import.
  Export can leave out the attribute-encryption key. No AD data included.
- docker/compose.dev.yaml: live-reload dev stack that bind-mounts the working
  tree. docker/php/Dockerfile is now multi-stage (base -> dev / prod).
- .github/workflows/release.yml: on every vX.Y.Z tag, builds the prod image and
  pushes gitea.kzbikowski.pl/kzbkowski/adconsole:{X.Y.Z,X.Y,latest}.

Changed
- docker/compose.yaml: self-contained prod image (app code + composer install
  --no-dev baked in via COPY); persistent state in docker/data/{app_storage,db};
  defaults to the released image (ADCONSOLE_VERSION pins a tag, ADCONSOLE_IMAGE
  replaces the ref). Apache now honours public/.htaccess (AllowOverride All).
  Run from the repo root with --env-file .env.
- Repo root now holds only README.md; CHANGELOG / CONTRIBUTING / SECURITY /
  CODE_OF_CONDUCT moved under docs/.

Upgrade notes: docs/upgrading.md#v110--docker-layout. Full log: docs/CHANGELOG.md.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JKT9p3bfP8RZesExdYCS52
2026-09-10 09:13:04 +02:00

4.8 KiB

Development

Local setup

git clone https://gitea.kzbikowski.pl/kzbkowski/ADconsle.git adconsole && cd adconsole
composer install
cp .env.example .env
php artisan key:generate

Edit .env for a dev box:

APP_ENV=local
APP_DEBUG=true
LOG_LEVEL=debug
DB_CONNECTION=sqlite      # simplest; then: touch database/database.sqlite
php artisan migrate
php artisan serve

You still need a reachable domain controller for the AD-backed screens. Without one, the auth and list pages will error — the test suite does not need a DC (it fakes the guard and mocks LdapRecord).

Local setup — Docker (live reload)

git clone https://gitea.kzbikowski.pl/kzbkowski/ADconsle.git adconsole && cd adconsole
cp .env.example .env        # APP_ENV=local, APP_DEBUG=true, real LDAP_* / AD_*
docker compose --env-file .env -f docker/compose.dev.yaml up --build

Run from the repo root; --env-file .env lets Compose interpolate ${DB_*} from the repo-root .env (the file lives in docker/). Set export COMPOSE_FILE=docker/compose.dev.yaml COMPOSE_ENV_FILES=.env once to drop the flags.

The working tree is bind-mounted over /var/www/html, so PHP / Blade / CSS / JS edits apply on the next request (the dev image target sets opcache.revalidate_freq=0). On the first boot of a fresh clone the entrypoint runs composer install (with dev deps) and php artisan key:generate, then migrate. vendor/ lands back on the host, so your IDE resolves it too.

Database and storage/ are throwaway named volumes — add -v to docker compose … down to reset the box. MariaDB is published on localhost:3306. Run artisan / tools inside the container:

docker compose --env-file .env -f docker/compose.dev.yaml exec app php artisan migrate:fresh
docker compose --env-file .env -f docker/compose.dev.yaml exec app php artisan test
docker compose --env-file .env -f docker/compose.dev.yaml exec app vendor/bin/pint

compose.dev.yaml expects an external Traefik on traefik_public; without one, cp docker/compose.dev.override.yaml.template docker/compose.dev.override.yaml and add -f docker/compose.dev.override.yaml (publishes http://localhost:8080).

Tests

php artisan test                     # everything (~40, SQLite :memory:)
php artisan test --filter=Dashboard  # one file / group
composer test                        # config:clear + test
  • tests/Unit — pure logic (LdapAttributeHelper, AttributeCipher, MemberOfLoginGroup, OuTreeService).
  • tests/Feature — HTTP: auth, localisation, the About page, attribute config, the audit log and the user CSV export (RefreshDatabase), and the dashboard (seeds the file cache, no LDAP).
  • tests/TestCase::actingAsPanelAdmin() logs in a fake App\Ldap\User on the ldap guard so you can hit protected routes.

PHPUnit tags every test DEPR because PHP 8.5 deprecates a PDO constant PHPUnit touches. It is not a failure — look at the Tests: summary line.

Code style

Laravel Pint:

vendor/bin/pint            # fix
vendor/bin/pint --test     # check only (CI)
composer lint / composer format

Match the surrounding code: constructor property promotion, typed properties, short closures, App\Services for cross-cutting logic. Comments in the codebase are Polish — keep new ones consistent with the file you're editing.

Adding a translation string

  1. Add the key to both lang/pl/<ns>.php and lang/en/<ns>.php.
  2. Use __('<ns>.<key>') in Blade/PHP — never inline copy.
  3. Some existing lang/pl/* values are asserted verbatim by tests/Feature/AttributeConfigTest and AboutPageTest; run the suite after touching PL strings.

Adding an AD attribute to the UI

No code change needed for a plain attribute: /settings → Attributes → add key / label / ldap name / category / type / column. Computed or specially-encoded attributes (bit flags, FileTime) need a helper in App\Services\LdapAttributeHelper and wiring in the relevant controller.

Front-end

public/css/style.css and public/js/main.js are edited directly and served as-is — no build step. Keep the light/dark (data-bs-theme) treatment working for anything new: define colours as tokens on :root and override under [data-bs-theme="dark"].

Database changes

New migrations go in database/migrations. Remember the project rule: no AD data in SQL — migrations are for app infrastructure and panel_settings-style config only. PanelSettingsService is the access point for panel config; don't read the table directly from controllers.

Handy commands

php artisan route:list --path=users
php artisan tinker
php artisan optimize:clear     # after .env / config edits
php artisan migrate:fresh      # dev DB reset (infra tables only)