Files
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

133 lines
4.8 KiB
Markdown

# Development
## Local setup
```sh
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
```
```sh
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)
```sh
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:
```sh
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
```sh
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](https://laravel.com/docs/pint):
```sh
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
```sh
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)
```