A containerized .NET 10.0 REST API for creating, sharing, and comparing Eurovision Song Contest rankings.
This project is designed to run as a "sidecar" application alongside other services (like Umami), using a shared PostgreSQL database with a dedicated ranker schema.
- Framework: .NET 10.0 (Web API)
- Database: PostgreSQL 15+
- Data Access: Dapper (Raw SQL)
- Migrations: Flyway
- Auth: JWT (Bearer Token) + BCrypt
- Infrastructure: Docker & Docker Compose
- Docker Desktop (or Docker Engine + Compose)
- (Optional) .NET 10.0 SDK for local non-containerized debugging
The application relies on environment variables for configuration.
- Navigate to the
EurovisionRanker.Apidirectory. - Copy the template file:
cp .env.template .env
- Open
.envand configure your secrets (Database credentials, JWT Secret, etc.).
This is the recommended way to run the application locally. It spins up the API, a local PostgreSQL instance, and runs Flyway migrations automatically.
docker-compose up --build- API URL:
http://localhost:5001(or whateverAPI_PORTyou defined in .env) - Database Port:
5488(Exposed for local inspection tools)
Once the container is running, access the Swagger UI to test endpoints:
http://localhost:5001/swagger/index.html
(Note: Adjust the port 5001 if you changed API_PORT in your .env file)
This project uses a specific schema strategy to allow co-existence with other applications on a shared database.
- Schema:
ranker(All tables are isolated here) - Migrations: SQL scripts are located in
db/migration. Flyway applies these automatically on container startup. - Search Path: The application connects with
SearchPath=ranker, so SQL queries do not need to prefix tables (e.g.,SELECT * FROM usersworks automatically).
users: Auth and profile data.ranking: User rankings for specific years (stored as text strings).groups: Groups for comparing rankings.group_member: Link table for users joining groups.
- Dapper: Dapper is used for high-performance data access. Ensure strict typing is used in DTOs.
- Authentication: Endpoints are secured via JWT. Use the
/api/Auth/loginendpoint to retrieve a token, then authorize in Swagger usingBearer <your-token>.