514 lines
10 KiB
Markdown
514 lines
10 KiB
Markdown
# 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 <repository-url>
|
|
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 <token>
|
|
```
|
|
|
|
## 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
|