FEATURE - Auth improvements See merge request guitartech/guitartech-auth-service!19 |
||
|---|---|---|
| deploy | ||
| gradle/wrapper | ||
| src | ||
| .env.example | ||
| .gitattributes | ||
| .gitignore | ||
| .gitlab-ci.yml | ||
| build.gradle | ||
| CLAUDE.md | ||
| docker-compose.yml | ||
| Dockerfile | ||
| gradlew | ||
| gradlew.bat | ||
| guitartech-auth-service.code-workspace | ||
| PLAN.md | ||
| README.md | ||
| settings.gradle | ||
guitartech-auth-service
A Spring Boot 4.0.1 REST API for user authentication and management. Implements JWT-based authentication with user registration, login, and profile management endpoints.
Quick Start
Prerequisites
- JDK 21+
- PostgreSQL 16 (running locally or via Docker)
- Gradle (included via wrapper:
./gradlew)
Local Development
-
Set up environment variables:
source .env.localThis loads
JWT_SECRETandDB_PASSWORDfor local development. -
Start PostgreSQL:
docker run -d \ --name guitartech-postgres \ -e POSTGRES_DB=guitartech_auth_service \ -e POSTGRES_PASSWORD=postgres \ -p 5432:5432 \ postgres:16-alpine -
Run the application: Using the Spring Boot Dashboard extension in VS Code:
- Source
.env.localin your terminal:source .env.local - Click the run button in the Dashboard
Or via CLI:
source .env.local ./gradlew bootRun - Source
-
Verify it's running:
curl http://localhost:8080/actuator/health
The application will automatically apply Liquibase database migrations on startup.
API Endpoints
Public Endpoints
-
POST /api/auth/register — Register a new user
{ "username": "john_doe", "password": "SecurePass123!", "email": "john@example.com" } -
POST /api/auth/login — Authenticate and get JWT token
{ "usernameOrEmail": "john_doe", "password": "SecurePass123!" }
Protected Endpoints (Require JWT Bearer Token)
- PUT /api/users/{id} — Update your profile
Authorization: Bearer <jwt-token>
Building & Testing
./gradlew clean build # Full clean build
./gradlew build -x test # Build without tests
./gradlew test # Run all tests
./gradlew test --tests SomeTest # Run a specific test
Tests use Testcontainers with a real PostgreSQL database (containerized), not an in-memory DB.
macOS Note: For best performance with Testcontainers, use Orbstack instead of Docker Desktop. Orbstack is lightweight, faster, and handles container networking better on macOS.
Environment Variables
Create a .env.local file (git-ignored) with:
export JWT_SECRET="your-secret-min-64-chars"
export DB_PASSWORD="postgres"
Or set them directly:
JWT_SECRET=my-secret DB_PASSWORD=postgres ./gradlew bootRun
For Deployed Environments
The app reads these environment variables at runtime:
JWT_SECRET— JWT signing secret (required in production)SPRING_DATASOURCE_URL— Database URL (defaults to localhost)SPRING_DATASOURCE_USERNAME— Database userSPRING_DATASOURCE_PASSWORD— Database password
Database
Local Setup
The default application.properties connects to:
jdbc:postgresql://localhost:5432/guitartech_auth_service
username: postgres
password: postgres
Start PostgreSQL with the Docker command above, and migrations run automatically on app startup.
Resetting the Database Locally
# Connect to PostgreSQL
psql -U postgres -d guitartech_auth_service
# Drop tables to reset
DROP TABLE auth_user CASCADE;
DROP TABLE database_changelog CASCADE;
DROP TABLE database_changelog_lock CASCADE;
Then restart the app — migrations will re-apply.
Security
This project uses GitLab's free SAST (Static Application Security Testing) to automatically scan for vulnerabilities:
- Semgrep — Scans Java source code for security issues and code quality problems
- SpotBugs — Detects common Java bugs
- Runs on all merge requests and branches before code can be merged
- Results appear in the Merge Request pipeline UI
To view SAST reports:
- Go to your merge request in GitLab
- Click the Checks or Pipeline tab
- Look for SAST job details and any detected issues
Deployment
This service deploys to production only via GitLab CI/CD:
- Production (guitartech.app) — Manual deployment to VPS (requires manual trigger in GitLab pipeline)
The pipeline automatically runs:
- Build — Compiles code
- Test — Runs tests + SAST security scanning
- Containerize — Builds Docker image
- Publish — Pushes image to registry (main branch only)
- Deploy — Manual production deployment (main branch only)
Local Development: Run locally with source .env.local && ./gradlew bootRun
Production Setup: Runs in Docker Compose on a 2GB VPS with Postgres. See docker-compose.yml for configuration.
Project Structure
src/main/java/tech/guitar/auth/
├── GuitartechAuthServiceApplication.java # Entry point
├── config/SecurityConfig.java # Spring Security + JWT config
├── controller/ # REST endpoints
├── service/ # Business logic
├── repository/ # Data access (JPA)
├── entity/ # JPA entities
├── dto/ # Request/response DTOs
├── filter/ # JWT validation filter
├── mapper/ # Entity converters
└── exception/ # Error handling
src/main/resources/
├── application.properties # Configuration
└── db/changelog/ # Liquibase migrations
src/test/
├── AbstractIntegrationTest.java # Base test class
├── repository/ # Repository tests
└── testutil/ # Test utilities
Key Features
- JWT Authentication — HS512 algorithm, 24-hour expiration
- Password Security — BCrypt hashing (strength factor 12)
- Input Validation — DTO-level with Jakarta validation annotations
- Database Migrations — Liquibase with UTC timestamps
- Global Exception Handling — Consistent error responses
- Comprehensive Tests — Integration tests with real DB
Development Workflow
- Create a feature branch off
main - Write tests first (repository, service, controller layers)
- Implement the feature
- Run all tests locally:
./gradlew test - Open a merge request
- GitLab CI automatically runs:
- Build: Compiles code
- Test: Runs unit/integration tests + SAST security scanning
- Containerize: Builds Docker image
- All must pass before merge
- Merge to
mainonce approved - Publish: Image is pushed to GitLab Container Registry
- Manually trigger production deployment from the GitLab pipeline UI (only available for
mainbranch)
Test Coverage
The project enforces 80% minimum code coverage on the main branch:
- On main branch: Pipeline fails if coverage drops below 80%
- On merge requests: Coverage below 80% is flagged as a warning (doesn't block merge)
- View locally:
./gradlew jacocoTestReportto generate coverage report
This ensures code quality stays consistent while allowing flexibility during feature development on branches.
Useful Commands
# Format and check code
./gradlew spotlessApply # Auto-format code
# View test coverage
./gradlew jacocoTestReport
# Clean up everything
./gradlew clean
# Run integration tests only
./gradlew test -i integration
Troubleshooting
"Could not connect to PostgreSQL"
- Ensure PostgreSQL is running:
docker ps | grep postgres - Check credentials match
.env.localorapplication.properties
"JWT_SECRET is not set"
- Run
source .env.localbefore starting the app - Or set:
export JWT_SECRET=<value>
"Liquibase migration failed"
- Check database permissions and connectivity
- Review migration files in
src/main/resources/db/changelog/migrations/
Support
For issues or questions, refer to CLAUDE.md for detailed architecture and testing guidelines.