Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
1850c14
feat: add user authentication (#2)
martinydeAI Jun 11, 2026
349e098
fix(ci): grant db user access to db_test* via mariadb init SQL
martinydeAI Jun 11, 2026
9523285
chore(taskfile): self-heal test DB privileges before running PHPUnit
martinydeAI Jun 11, 2026
e2c8c80
fix(ci): create db_test in the mariadb init SQL too
martinydeAI Jun 11, 2026
4f88b53
chore(taskfile): apply migrations as part of site-install
martinydeAI Jun 11, 2026
6b712de
docs: trim the redundant site-install note from user-creation block
martinydeAI Jun 11, 2026
46e417c
style: drop vertical phpdoc alignment; shorten @param/@return blurbs
martinydeAI Jun 11, 2026
436ab92
Merge branch 'develop' into feature/issue-2-user-login
martinydeAI Jun 15, 2026
cedcaa7
refactor(test-db): bootstrap via Symfony console, no init SQL
martinydeAI Jun 15, 2026
61c91f4
refactor(migration): port initial user-table migration to Schema API
martinydeAI Jun 15, 2026
4d8cffd
docs(commands): drop Taskfile usage line from user-command PHPDoc
martinydeAI Jun 15, 2026
7ef32d3
style(php-cs-fixer): drop local phpdoc_align override
martinydeAI Jun 15, 2026
6b0a0f1
test: split suite into unit + integration with DAMA isolation
martinydeAI Jun 15, 2026
335e417
feat(twig): extract Form/Label, Form/Input, Form/Button components
martinydeAI Jun 15, 2026
4d53cef
Update comment
martinyde Jun 15, 2026
3554d72
test: dedicated integration bootstrap loads fixtures once
martinydeAI Jun 16, 2026
eaa96c3
docs(test): shorten UserFixturesTest unit docblock
martinydeAI Jun 16, 2026
3c6c99e
Update .env.test
martinyde Jun 16, 2026
f564c8b
Updated .env.test
martinyde Jun 16, 2026
4e48160
Applied coding standards
martinyde Jun 17, 2026
a648c1a
Merge branch 'develop' into feature/issue-2-user-login
martinydeAI Jun 17, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .env
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,7 @@ BRAND_NAME="AI Bibliotek"
BRAND_TAGLINE="del & hjemtag assistenter"
BRAND_INITIALS="AI"
###< brand identity ###

###> doctrine/doctrine-bundle ###
DATABASE_URL="mysql://db:db@mariadb:3306/db?serverVersion=10.11.16-MariaDB&charset=utf8mb4"
###< doctrine/doctrine-bundle ###
2 changes: 2 additions & 0 deletions .env.test
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# define your env variables for the test env here
KERNEL_CLASS='App\Kernel'
APP_SECRET='$ecretf0rt3st'

DATABASE_URL="mysql://root:password@mariadb:3306/db_test?serverVersion=10.11.16-MariaDB&charset=utf8mb4"
5 changes: 4 additions & 1 deletion .github/workflows/tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,11 @@ jobs:
- name: Build Tailwind CSS
run: docker compose run --rm phpfpm bin/console tailwind:build

- name: Create the test database
run: docker compose run --rm phpfpm bin/console --env=test doctrine:database:create --if-not-exists --no-interaction

- name: Run PHPUnit with coverage
run: docker compose run -e XDEBUG_MODE=coverage --rm phpfpm vendor/bin/phpunit --coverage-clover=coverage/clover.xml
run: docker compose run -e XDEBUG_MODE=coverage --rm phpfpm vendor/bin/phpunit --bootstrap=tests/bootstrap_integration.php --coverage-clover=coverage/clover.xml

- name: Enforce coverage threshold (100%)
run: docker compose run --rm phpfpm vendor/bin/coverage-check coverage/clover.xml 100
22 changes: 22 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,28 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
`nav_toggle_controller` driving the mobile menu, and a
`block-on-label` GitHub Action providing a per-PR merge gate
([#40](https://github.com/itk-dev/ai-lib/issues/40)).
- User authentication: `User` Doctrine entity (email, hashed password,
roles), `UserRepository` (with `PasswordUpgraderInterface`), the
`UserManager` service that hides persistence + hashing, form-login
firewall + `/login` + `/logout`, fixtures for two baseline users
(`alice@example.test`, `bob@example.test` — password `password`),
console commands `app:user:create` and `app:user:change-password`,
and end-to-end functional + unit tests
([#2](https://github.com/itk-dev/ai-lib/issues/2)).
- PHPUnit suite split into `unit` (no database) and `integration` (full
kernel) testsuites under `tests/Unit/` and `tests/Integration/`, with
transactional database isolation per integration test via
`dama/doctrine-test-bundle`. The integration suite uses a dedicated
`tests/bootstrap_integration.php` that builds the schema from ORM
metadata and loads baseline `UserFixtures` once before any test;
DAMA's per-test transaction rolls back mutations so the baseline
persists. The default `tests/bootstrap.php` is minimal and is used
by `task test-unit`. `task test-unit` and `task test-integration`
expose the suites individually.
- Reusable Twig form components under `templates/components/Form/`:
`Form/Label`, `Form/Input`, and `Form/Button` (with `variant` and
`size` props for future styling variants). The `/login` template
consumes them instead of inlining the input/label/button markup.
- Site chrome (header with brand + nav, footer) in
`templates/base.html.twig`, with the Fraunces/Geist font stack
preloaded from Google Fonts.
Expand Down
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,21 @@ task open
The site is served through Traefik on a `*.local.itkdev.dk` domain (the exact
URL is printed by the start task).

### Creating the first user

```sh
# Option A — load the local-dev fixtures (alice + bob, password `password`)
task console -- doctrine:fixtures:load -n

# Option B — create a single user explicitly
task console -- app:user:create alice@example.test secret

# Change an existing user's password
task console -- app:user:change-password alice@example.test newsecret
```

Then sign in at `/login`.

## Testing

Tests live under `tests/` (PSR-4 namespace `App\Tests\`) and run with
Expand Down
28 changes: 25 additions & 3 deletions Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,12 @@ tasks:
# ---- Lifecycle --------------------------------------------------------

site-install:
desc: 'Pull images, start the stack, and install Composer dependencies.'
desc: 'Pull images, start the stack, install Composer dependencies, and apply database migrations.'
cmds:
- task compose -- pull
- task compose -- up --detach --remove-orphans --wait
- task composer-install
- task console -- doctrine:migrations:migrate --no-interaction
silent: true

# ---- Composer ---------------------------------------------------------
Expand Down Expand Up @@ -91,16 +92,37 @@ tasks:

# ---- Tests ------------------------------------------------------------

db-prepare-test:
desc: 'Ensure the test database exists (idempotent).'
cmds:
- task console -- --env=test doctrine:database:create --if-not-exists --no-interaction
silent: true

test:
desc: 'Run the PHPUnit test suite (no coverage).'
cmds:
- task compose-exec -- phpfpm vendor/bin/phpunit
- task: db-prepare-test
- task compose-exec -- phpfpm vendor/bin/phpunit --bootstrap=tests/bootstrap_integration.php
silent: true

test-unit:
desc: 'Run only the unit suite (no database).'
cmds:
- task compose-exec -- phpfpm vendor/bin/phpunit --testsuite=unit
silent: true

test-integration:
desc: 'Run only the integration suite.'
cmds:
- task: db-prepare-test
- task compose-exec -- phpfpm vendor/bin/phpunit --testsuite=integration --bootstrap=tests/bootstrap_integration.php
silent: true

test-coverage:
desc: 'Run PHPUnit with coverage and enforce the 100% gate.'
cmds:
- task compose -- exec -e XDEBUG_MODE=coverage phpfpm vendor/bin/phpunit --coverage-clover=coverage/clover.xml
- task: db-prepare-test
- task compose -- exec -e XDEBUG_MODE=coverage phpfpm vendor/bin/phpunit --bootstrap=tests/bootstrap_integration.php --coverage-clover=coverage/clover.xml
- task compose-exec -- phpfpm vendor/bin/coverage-check coverage/clover.xml 100
silent: true

Expand Down
7 changes: 7 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,17 @@
"php": ">=8.4",
"ext-ctype": "*",
"ext-iconv": "*",
"doctrine/doctrine-bundle": "^3.2",
"doctrine/doctrine-migrations-bundle": "^4.0",
"doctrine/orm": "^3.6",
"symfony/asset": "^8.1",
"symfony/asset-mapper": "^8.1",
"symfony/console": "~8.1.0",
"symfony/dotenv": "~8.1.0",
"symfony/flex": "^2",
"symfony/framework-bundle": "~8.1.0",
"symfony/runtime": "~8.1.0",
"symfony/security-bundle": "~8.1.0",
"symfony/stimulus-bundle": "^3.1",
"symfony/translation": "~8.1.0",
"symfony/twig-bundle": "~8.1.0",
Expand All @@ -24,12 +28,15 @@
"twig/twig": "^2.12 || ^3.0"
},
"require-dev": {
"dama/doctrine-test-bundle": "^8.0",
"doctrine/doctrine-fixtures-bundle": "^4.3",
"ergebnis/composer-normalize": "^2.52",
"friendsofphp/php-cs-fixer": "^3.95.5",
"phpunit/phpunit": "^11.5",
"rregeer/phpunit-coverage-check": "^0.3.1",
"symfony/browser-kit": "~8.1.0",
"symfony/css-selector": "~8.1.0",
"symfony/maker-bundle": "^1.67",
"symfony/phpunit-bridge": "~8.1.0",
"vincentlanglet/twig-cs-fixer": "^3.14"
},
Expand Down
Loading