# MTG Search - Magic The Gathering Card Search Platform A full-stack web application for searching and exploring Magic The Gathering cards with user authentication, built with Spring Boot, Vue.js, PostgreSQL, and deployed with Docker. ## Architecture Overview ``` ├── Backend (Java 21, Spring Boot 3.2.5) │ ├── REST API with OpenAPI/Swagger documentation │ ├── JWT-based authentication │ ├── PostgreSQL database with jOOQ ORM │ ├── Flyway database migrations │ ├── Comprehensive logging with Logback │ └── JUnit 5 and integration tests │ ├── Frontend (Vue 3, TypeScript, Vite) │ ├── Single Page Application (SPA) │ ├── Responsive UI with CSS Grid/Flexbox │ ├── Pinia state management │ ├── Vue Router with auth guards │ └── Axios HTTP client with JWT interceptors │ ├── Database (PostgreSQL 16) │ ├── Schema managed by Flyway migrations │ ├── jOOQ-generated DTOs and repositories │ └── Indexed queries for performance │ └── Deployment ├── Docker multi-stage build ├── Docker Compose for local dev └── GitLab CI/CD pipeline ``` ## Prerequisites - **Java 21** or later - **Node.js 20+** and npm 10+ - **PostgreSQL 16+** - **Docker & Docker Compose** (for containerized setup) - **Git** ## Quick Start ### Using Docker Compose (Recommended) ```bash # Clone the repository git clone cd mtg-search # Start all services (PostgreSQL, Backend, built Frontend) docker-compose up --build # Backend will be available at: http://localhost:8080 # Frontend will be served by the backend ``` ### Local Development Setup #### 1. Database Setup ```bash # Start PostgreSQL (using Docker) docker run --name mtgsearch-postgres \ -e POSTGRES_DB=mtgsearch \ -e POSTGRES_USER=postgres \ -e POSTGRES_PASSWORD=postgres \ -p 5432:5432 \ -d postgres:17-alpine # Or use your local PostgreSQL installation ``` #### 2. Backend Setup ```bash cd backend # Build the project ../gradlew build # Run the application ../gradlew bootRun # Backend starts on http://localhost:8080 # Swagger UI available at: http://localhost:8080/swagger-ui.html # API Docs available at: http://localhost:8080/v3/api-docs ``` #### 3. Frontend Setup ```bash cd frontend # Install dependencies npm install # Start development server npm run dev # Frontend starts on http://localhost:5173 ``` ## API Endpoints ### Authentication - **POST** `/api/v1/auth/register` - Register a new user ```json { "username": "john_doe", "email": "john@example.com", "password": "SecurePassword123!" } ``` - **POST** `/api/v1/auth/login` - Login and get JWT token ```json { "username": "john_doe", "password": "SecurePassword123!" } ``` Returns: ```json { "token": "eyJhbGc...", "id": 1, "username": "john_doe", "email": "john@example.com" } ``` - **GET** `/api/v1/auth/health` - Health check (no auth required) ### Protected Endpoints All protected endpoints require JWT token in Authorization header: ``` Authorization: Bearer ``` ## Building ### Build Backend ```bash ./gradlew clean build # Build outputs to: backend/build/libs/ ``` ### Build Frontend ```bash cd frontend npm run build # Build outputs to: backend/src/main/resources/static/ ``` ### Build Full Docker Image ```bash docker build -t mtgsearch:latest . ``` ## Testing ### Backend Unit Tests ```bash ./gradlew test ``` ### Backend Integration Tests ```bash ./gradlew integrationTest ``` ### Frontend Tests ```bash cd frontend npm run test npm run test:ui # Opens UI dashboard ``` ### All Tests with Coverage ```bash ./gradlew test jacocoTestReport ``` ## Configuration ### Environment Variables Create a `.env` file in the project root: ```env # Database DB_URL=jdbc:postgresql://localhost:5432/mtgsearch DB_USER=postgres DB_PASSWORD=postgres # JWT JWT_SECRET=your-secret-key-change-in-production JWT_EXPIRATION=86400 # Frontend VITE_API_URL=http://localhost:8080 ``` ### Application Properties Backend configuration in `backend/src/main/resources/application.yml`: ```yaml spring: datasource: url: jdbc:postgresql://localhost:5432/mtgsearch username: postgres password: postgres jpa: hibernate: ddl-auto: validate app: jwt: secret: ${JWT_SECRET:your-secret-key} expiration: ${JWT_EXPIRATION:86400} ``` ## Database Migrations Migrations are managed by Flyway and located in `backend/src/main/resources/db/migration/` ### Adding a New Migration 1. Create a new file: `V2__Add_new_table.sql` 2. Write SQL migration 3. Run application - Flyway will auto-apply migrations Example migration: ```sql -- V2__Add_cards_table.sql CREATE TABLE IF NOT EXISTS cards ( id BIGSERIAL PRIMARY KEY, name VARCHAR(255) NOT NULL, created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ); ``` ## Logging Logs are configured in `backend/src/main/resources/logback-spring.xml` - **Log Location**: `logs/mtg-search.log` - **Error Logs**: `logs/mtg-search-error.log` - **Max File Size**: 100MB - **Retention**: 30 days - **Compression**: Automatic gzip compression View logs: ```bash tail -f logs/mtg-search.log tail -f logs/mtg-search-error.log ``` ## Development Workflow ### Code Generation The project uses OpenAPI Generator and jOOQ for code generation: ```bash # Generate server stubs from OpenAPI spec ./gradlew openApiGenerate # Generate jOOQ entities from database schema ./gradlew generateJooqCode ``` ### Code Quality ```bash # Format code ./gradlew spotlessApply # Run static analysis ./gradlew check # Frontend linting cd frontend npm run lint ``` ## Deployment ### Staging Deployment ```bash git checkout develop git merge feature-branch git push origin develop # GitLab CI will automatically build and deploy to staging ``` ### Production Deployment ```bash git tag v0.2.0 git push origin v0.2.0 # GitLab CI will build, test, and deploy to production ``` ### Manual Deployment ```bash # Build Docker image docker build -t mtgsearch:v0.1.0 . docker tag mtgsearch:v0.1.0 your-registry/mtgsearch:v0.1.0 # Push to registry docker push your-registry/mtgsearch:v0.1.0 # Pull and run on server docker pull your-registry/mtgsearch:v0.1.0 docker run -d \ -e SPRING_DATASOURCE_URL=jdbc:postgresql://db-host:5432/mtgsearch \ -e SPRING_DATASOURCE_USERNAME=postgres \ -e SPRING_DATASOURCE_PASSWORD=secure-password \ -e JWT_SECRET=your-production-secret \ -p 8080:8080 \ --name mtgsearch \ your-registry/mtgsearch:v0.1.0 ``` ## CI/CD Pipeline The project includes a comprehensive GitLab CI/CD pipeline (`.gitlab-ci.yml`): 1. **Build Stage** - Compiles Java backend - Builds Vue.js frontend - Caches dependencies 2. **Test Stage** - Unit tests - Integration tests with PostgreSQL - Code quality checks 3. **Docker Stage** - Builds multi-stage Docker image - Pushes to registry 4. **Deploy Stage** - Deploys to staging with manual trigger - Deploys to production on version tags ## Project Structure ``` mtg-search/ ├── backend/ │ ├── src/ │ │ ├── main/ │ │ │ ├── java/net/moustos/mtgsearch/ │ │ │ │ ├── MtgSearchApplication.java │ │ │ │ ├── config/ │ │ │ │ ├── controller/ │ │ │ │ ├── service/ │ │ │ │ ├── repository/ │ │ │ │ ├── model/ │ │ │ │ └── security/ │ │ │ └── resources/ │ │ │ ├── application.yml │ │ │ ├── logback-spring.xml │ │ │ └── db/migration/ │ │ └── test/ │ │ └── java/ │ └── build.gradle.kts │ ├── frontend/ │ ├── src/ │ │ ├── pages/ │ │ ├── components/ │ │ ├── services/ │ │ ├── stores/ │ │ ├── router/ │ │ ├── types/ │ │ ├── main.ts │ │ └── App.vue │ ├── public/ │ ├── index.html │ ├── package.json │ ├── vite.config.ts │ └── tsconfig.json │ ├── gradle/ ├── build.gradle.kts ├── settings.gradle.kts ├── gradle.properties ├── gradlew ├── gradlew.bat │ ├── Dockerfile ├── docker-compose.yml ├── .gitlab-ci.yml ├── .gitignore └── README.md ``` ## Troubleshooting ### Backend won't start ```bash # Check if port 8080 is already in use lsof -i :8080 # Check PostgreSQL is running psql -U postgres -h localhost -d mtgsearch -c "SELECT 1;" # View logs tail -f logs/mtg-search.log ``` ### Frontend connection issues - Check backend is running on 8080 - Check browser console for errors - Verify CORS settings in SecurityConfig.java ### Database migration failures ```bash # Check migration status ./gradlew flywayInfo # Repair migrations (use with caution) ./gradlew flywayRepair # Clean database (WARNING: deletes all data) ./gradlew flywayClean ``` ### Docker build fails ```bash # Clear Docker cache docker system prune -a # Rebuild with no cache docker build --no-cache -t mtgsearch:latest . ``` ## Performance Optimization ### Backend - Connection pooling: HikariCP configured with 10 max connections - Database indexing on frequently queried columns - Flyway async migration setup - Request caching headers ### Frontend - Code splitting with Vite - Lazy route loading - Production build minification - Gzip compression ### Database - Query result caching - Indexed columns for search operations - Batch operations optimization ## Security - **Password Hashing**: BCrypt with strength 12 - **JWT Tokens**: Auth0 library with HMAC256 - **CORS**: Configured for development (update for production) - **HTTPS**: Required for production deployment - **SQL Injection**: Protected via parameterized queries with jOOQ - **CSRF**: Disabled for API (JWT-based auth) ## Contributing 1. Create a feature branch: `git checkout -b feature/amazing-feature` 2. Commit changes: `git commit -m 'Add amazing feature'` 3. Push to branch: `git push origin feature/amazing-feature` 4. Open a Pull Request ## License MIT License - see LICENSE file for details ## Support For issues and questions: - Open an issue on GitLab - Check existing documentation - Review API Swagger docs at `/swagger-ui.html` ## Roadmap - [ ] Card search functionality with filters - [ ] Deck building feature - [ ] Social features (friends, sharing) - [ ] Mobile app - [ ] Advanced analytics - [ ] Magic Online API integration - [ ] Performance tuning for large datasets