Add role-based access control to the backend authentication system. The User
entity now carries a role field (default 'user'), JWT tokens include a 'role'
claim, and the login endpoint populates it from the database.
Changes:
- User entity: add role column (VARCHAR(20), default 'user') with getter/setter
- JwtService: add generateToken(email, role) overload and extractRole(token)
- AuthController: pass user.getRole() on login, 'user' on register
- Flyway V3: ALTER TABLE users ADD COLUMN role
- Flyway V4: seed admin user (admin@bilhalsning.se, role='admin')
- AuthControllerTest: add tests for admin role in token, role from DB on login
- JwtServiceTest: add tests for role extraction and default role
- UserServiceTest: assert role defaults to 'user' on createUser
Add POST /api/auth/login endpoint that authenticates users by email and
password, returning a JWT token on success. Also fixes a critical bug
where expired or malformed JWT tokens in the Authorization header caused
unhandled exceptions, crashing requests to all endpoints including public
ones like registration.
Changes:
- Add AuthController.login() endpoint with LoginRequest DTO
- Add UserService.authenticate() that validates credentials and throws
InvalidCredentialsException on failure
- Add InvalidCredentialsException and GlobalExceptionHandler handler
that maps it to 401 with Swedish error message
- Fix JwtAuthenticationFilter to catch JwtException (expired, malformed)
and pass through without crashing — the filter now acts as a graceful
enricher rather than a gatekeeper
- Add 5 controller tests for login endpoint (success, 401, validation)
- Add 4 service tests for authenticate() (success, email not found,
password mismatch, email normalization)
- Add 2 filter tests for expired and malformed token pass-through