Files
2026-04-28 02:31:41 +09:30

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