From f92d5da49c7351447d032c33b6fafb1260e29725 Mon Sep 17 00:00:00 2001 From: Jianming Fan <151937346+Jianming2024@users.noreply.github.com> Date: Thu, 18 Dec 2025 14:58:00 +0100 Subject: [PATCH 1/3] Implement of readme --- README.md | 284 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 167 insertions(+), 117 deletions(-) diff --git a/README.md b/README.md index 7f5312a..ece9495 100644 --- a/README.md +++ b/README.md @@ -1,169 +1,219 @@ # Dead Pigeons 🐦 (3rd Semester Project) - [Dead Pigeons](#dead-pigeons) - - [Environment](#environment) - - [Authorization](#authorization) - - [Anonymous](#anonymous) - - [Authenticated user](#authenticated-user) - - [Player only](#player-only) - - [Admin only](#admin-only) - - [Configuration](#configuration) - - [Linting](#linting) - - [Filtering / sorting / paging](#filtering--sorting--paging) - - [Testing](#testing) - - [Limitations](#limitations) + - [Live demo](#live-demo) + - [Run API](#run-api) + - [Run Client](#run-client) + - [Run Tests](#run-tests) + - [Prerequisites](#prerequisites) + - [Environment](#environment) + - [Configuration](#configuration) + - [API configuration](#api-configuration) + - [Client configuration](#client-configuration) + - [Testing](#testing) + - [How we test](#how-we-test) + - [Linting](#linting) + - [Authentication](#authentication) + - [JWT](#jwt) + - [Authorization](#authorization) + - [Anonymous (not logged in)](#anonymous-not-logged-in) + - [Authenticated user (role = Player or Admin)](#authenticated-user-role--player-or-admin) + - [Player only (role = Player)](#player-only-role--player) + - [Admin only (role = Admin)](#admin-only-role--admin) + - [Architecture / Data model](#architecture--data-model) + - [Deployment](#deployment) + - [Proxy & Frontend Integration](#proxy--frontend-integration) + - [Limitations](#limitations) + +## Dead Pigeons +This project was developed for the local sports club, Jerne IF. +It delivers a web-based solution that digitizes the game workflow, +making it easier to operate the game, manage players and boards, +and scale as participation grows. +Our project has Mobile-friendly UI (responsive layout for phone/tablet). + +## Live demo +- https://deadpigeons-frontend.fly.dev + email and password are stored in Wiseflow. + +### Run API +From repo root (adjust paths if yours differ): +```bash +cd server/api +dotnet run +``` +### Run Client +```bash +cd client +npm install +npm run dev +``` +### Run Tests +```bash +cd server/tests +dotnet test +``` ## Prerequisites - .NET SDK **9.x** - Node.js -- PostgreSQL -- Fly.io CLI (for deployment) +- PostgreSQL (Neon db) +- Fly.io CLI + Fly.io account (deployment) - Docker (for running PostgreSQL locally and for deployment) - GitHub account (for CI/CD) -- Fly.io account (for hosting) ## Environment Full-stack lottery web application with: - api: ASP.NET Core (.NET 9), EF Core + PostgreSQL - client: React + TypeScript + Tailwind CSS - tests: xUnit + Testcontainers + XUnit.DependencyInjection -- CI/CD: GitHub Actions + Docker + Fly.io -- infrastructure: Fly.io + PostgreSQL +- CI: GitHub Actions (build + tests) +- deployment: Docker + Fly.io +- infrastructure: Fly.io + PostgreSQL (Neon) - querying: sieve (filter/sort/paging) - authentication: JWT access tokens - documentation: Swagger / OpenAPI ## Configuration ### API configuration -Configuration (connection string and Jwt secret) are read from `server/api/appsettings.json` -Swagger enabled in development mode, see Program.cs -Sieve is enabled for selected list endpoints, filter/sort/paging via query parameters +- Configuration values (connection string and Jwt secret) are read from `server/api/appsettings.json`. +- Swagger is enabled (please see `server/api/Program.cs`). +- Sieve is enabled for selected list endpoints (filter/sort/paging via query parameters using `SieveModel`). -## Client configuration -VITE_API_URL is stored in .env file. -Build mode (dev/prod) settings -Proxy settings for local development in vite.config.ts +### Client configuration +- `VITE_API_URL` is stored in `client/.env`. +- Build modes: development vs production (Vite). +- Proxy settings for local development are configured in `client/vite.config.ts`. ### Testing -## How we test -xUnit tests for service methods: -Happy path + unhappy path -Testcontainers for isolated Postgres persistence -XUnit.DependencyInjection for test setup - -### Linting -Client linting is handled with ESLint (TypeScript + React rules). eslint.config.js contains the configuration. +#### How we test +- xUnit tests for service methods (happy path + unhappy path). +- Testcontainers for isolated PostgreSQL persistence. +- XUnit.DependencyInjection for test setup / DI wiring. + +## Linting +Client linting is handled with ESLint (TypeScript + React rules). +`eslint.config.js` contains the configuration. The client uses ESLint (v9 “flat config”) with TypeScript + React rules. - Config: `client/eslint.config.js` - Run lint: + - `cd client` - `npm run lint` -- `dist/` is ignored +- Ignored: + - `dist/` - Rules include: - `@eslint/js` - `typescript-eslint` - `eslint-plugin-react-hooks` - `eslint-plugin-react-refresh` (Vite) + +## Authentication +The API uses email + password login. +- Users log in with **email** and **password**. +- Passwords are hashed with **Argon2id** and never stored in plain text. +- On successful login, the API issues a **JWT access token**. +- The client must send the JWT with subsequent requests (typically in the `Authorization: Bearer ` header). + +## JWT +JWT access token details: +- Contains claims: + - `sub` = user ID + - `role` = user role (Admin / Player) +- Signed using **HMAC-SHA256** +- Valid for **8 hours** +- Automatically validated by ASP.NET middleware: + - signature validation + - expiration validation ## Authorization -We use role-based authorization policies. - -### Anonymous -(not logged in): no token required -- POST /api/auth/login - -### Authenticated user -(Admin + Player) -- Board: GET /api/board/user/{userId} -- Board price: GET /api/BoardPrice -- Transactions: GET /api/Transaction/user/{userId} -- User: GET /api/user + GET /api/user/me -- Game result: GET /api/games/draw/history - -### Player only -- Transactions: POST /api/Transaction/deposit -- Board: POST /api/board/user/purchase + PUT /api/board/{boardId}/auto-repeat + GET /api/board/purchase/status - -### Admin only -- Transactions: PUT /api/Transaction/{id}/status + GET /api/Transaction/pending -- User: POST /api/user + PATCH /api/user/{id}/activate + PATCH /api/user/{id}/deactivate -- Board: GET /api/board/admin/all - -### Limitations -- **No rate limiting / brute-force protection.** - Login endpoint does not implement throttling, lockout, or captcha, so it’s not hardened against repeated attempts. -- **No email verification / password reset.** - User registration does not include email verification or password reset flows. -- **No internationalization (i18n).** - The client does not support multiple languages. - -- - -- ** with mobile optimization.** - The client is specifically optimized for mobile devices. -- -### Authentication - - ** The API uses JWT-based authentication with Argon2id password hashing. -- Users log in using email and password -- Passwords are securely hashed with Argon2id and never stored in plain text -- On successful login, the API issues a JWT -- The JWT contains the user ID (sub) and role (role) and must be sent with subsequent requests - ** JWT details -- Signed using HMAC-SHA256 -- Valid for 8 hours -- Validated automatically by middleware (signature and expiration) - - - -### Deployment +We use role-based authorization policies (Admin / Player) and in some cases +resource-based rules (a Player can only access their own data). + +### Anonymous (not logged in) +No token required: +- `POST /api/auth/login` (login) + +### Authenticated user (role = Player or Admin) +Users must be logged in (JWT required). +**Boards** +- `GET /api/board/user/{userId}` (player = only own boards; admin = any user) + +**Board prices** +- `GET /api/BoardPrice` (accessible when logged in) + +**Game results** +- `GET /api/games/draw/history` (view past winning draws) + +### Player only (role = Player) +Players must be authenticated. + +**Boards** +- `GET /api/board/user/{userId}` (view own boards only) +- `POST /api/board/user/purchase` (purchase boards for self only) +- `PUT /api/board/{boardId}/auto-repeat` (set auto-repeat for own board only) +- `GET /api/board/purchase/status` (view own purchase status only) + +**Repeats** +- `GET /api/repeat/me` (own repeats only) +- `POST /api/repeat` (create repeat for self only) +- `POST /api/repeat/{id}/stop` (stop own repeat only) + +**Transactions** +- `POST /api/Transaction/deposit` (create deposit for self only) +- `GET /api/Transaction/user/{userId}` (view own transactions only) + +### Admin only (role = Admin) +Admins must be authenticated. +**Admin game management** +- `POST /api/admin/games/draw` (trigger draw) +- `GET /api/admin/games/draw/status` (view draw status) +- `GET /api/admin/games/winners/summary` (view winners summary) +- `GET /api/admin/games/draw/history` (view draw history) + +**Users** +- `POST /api/user` (create user) +- `PATCH /api/user/{id}/activate` (activate user) +- `PATCH /api/user/{id}/deactivate` (deactivate user) +- `GET /api/user` (view all users) + +**Boards** +- `GET /api/board/admin/all` (view all boards) +- `GET /api/board/user/{userId}` (admin can view any user’s boards) + +**Transactions** +- `GET /api/Transaction/pending` (view pending transactions) +- `PUT /api/Transaction/{id}/status` (approve/reject transaction) + +## Architecture / Data model +> Data model diagram: +![DBdeadpigeons.png](client/public/DBdeadpigeons.png) - ** The backend is deployed using Docker and Fly.io. +## Deployment +** The backend is deployed using Docker and Fly.io. - The API is built with a multi-stage Docker build - A lightweight ASP.NET runtime image is used in production - Deployed to Fly.io in the fra region - Runs on port 8080 with HTTPS enforced -- Fly.io manages TLS, scaling, and machine lifecycle - ** Configuration +- Fly.io manages TLS, scaling, and machine lifecycle + ** Configuration - Database connection and JWT secret are provided via AppSettings - In production, secrets are supplied using environment variables / Fly.io secrets - ### Proxy & Frontend Integration - - Frontend runs on http://localhost:5173 - API requests are proxied to the backend - CORS allows the local frontend origin - ** Production + ** Production - Frontend and backend are hosted separately - Backend is accessed over HTTPS via Fly.io - CORS allows only the production frontend domain -This setup ensures secure and smooth communication in both development and production environments. - -### Run API -From repo root (adjust paths if yours differ): -```bash -cd server/api -dotnet run -``` -### Run Client -```bash -cd client -npm install -npm run dev -``` - -### Run Tests -```bash -cd server/tests -dotnet test - - - -``` -![DBdeadpigeons.png](client/public/DBdeadpigeons.png) - - - - + This setup ensures secure and smooth communication in both development and production environments. +## Limitations +- **No rate limiting / brute-force protection.** + Login endpoint does not implement throttling, lockout, or captcha, so it’s not hardened against repeated attempts. +- **No email verification / password reset.** + User registration does not include email verification or “forgot password” functionality. +- **No internationalization (i18n).** + The client UI does not support multiple languages. From c392770f3a44673a932daa580a479c3719eaa2c5 Mon Sep 17 00:00:00 2001 From: Jianming Fan <151937346+Jianming2024@users.noreply.github.com> Date: Thu, 18 Dec 2025 15:04:23 +0100 Subject: [PATCH 2/3] implement of readme --- README.md | 65 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 33 insertions(+), 32 deletions(-) diff --git a/README.md b/README.md index ece9495..ee10e16 100644 --- a/README.md +++ b/README.md @@ -1,34 +1,34 @@ # Dead Pigeons 🐦 (3rd Semester Project) - [Dead Pigeons](#dead-pigeons) - - [Live demo](#live-demo) - - [Run API](#run-api) - - [Run Client](#run-client) - - [Run Tests](#run-tests) - - [Prerequisites](#prerequisites) - - [Environment](#environment) - - [Configuration](#configuration) - - [API configuration](#api-configuration) - - [Client configuration](#client-configuration) - - [Testing](#testing) - - [How we test](#how-we-test) - - [Linting](#linting) - - [Authentication](#authentication) - - [JWT](#jwt) - - [Authorization](#authorization) - - [Anonymous (not logged in)](#anonymous-not-logged-in) - - [Authenticated user (role = Player or Admin)](#authenticated-user-role--player-or-admin) - - [Player only (role = Player)](#player-only-role--player) - - [Admin only (role = Admin)](#admin-only-role--admin) - - [Architecture / Data model](#architecture--data-model) - - [Deployment](#deployment) - - [Proxy & Frontend Integration](#proxy--frontend-integration) - - [Limitations](#limitations) + - [Live demo](#live-demo) + - [Run API](#run-api) + - [Run Client](#run-client) + - [Run Tests](#run-tests) + - [Prerequisites](#prerequisites) + - [Environment](#environment) + - [Configuration](#configuration) + - [API configuration](#api-configuration) + - [Client configuration](#client-configuration) + - [Testing](#testing) + - [How we test](#how-we-test) + - [Linting](#linting) + - [Authentication](#authentication) + - [JWT](#jwt) + - [Authorization](#authorization) + - [Anonymous (not logged in)](#anonymous-not-logged-in) + - [Authenticated user (role = Player or Admin)](#authenticated-user-role--player-or-admin) + - [Player only (role = Player)](#player-only-role--player) + - [Admin only (role = Admin)](#admin-only-role--admin) + - [Architecture / Data model](#architecture--data-model) + - [Deployment](#deployment) + - [Proxy & Frontend Integration](#proxy--frontend-integration) + - [Limitations](#limitations) ## Dead Pigeons -This project was developed for the local sports club, Jerne IF. -It delivers a web-based solution that digitizes the game workflow, -making it easier to operate the game, manage players and boards, +This project was developed for the local sports club, Jerne IF. +It delivers a web-based solution that digitizes the game workflow, +making it easier to operate the game, manage players and boards, and scale as participation grows. Our project has Mobile-friendly UI (responsive layout for phone/tablet). @@ -80,7 +80,7 @@ Full-stack lottery web application with: - Swagger is enabled (please see `server/api/Program.cs`). - Sieve is enabled for selected list endpoints (filter/sort/paging via query parameters using `SieveModel`). -### Client configuration +### Client configuration - `VITE_API_URL` is stored in `client/.env`. - Build modes: development vs production (Vite). - Proxy settings for local development are configured in `client/vite.config.ts`. @@ -92,7 +92,7 @@ Full-stack lottery web application with: - XUnit.DependencyInjection for test setup / DI wiring. ## Linting -Client linting is handled with ESLint (TypeScript + React rules). +Client linting is handled with ESLint (TypeScript + React rules). `eslint.config.js` contains the configuration. The client uses ESLint (v9 “flat config”) with TypeScript + React rules. @@ -103,11 +103,11 @@ The client uses ESLint (v9 “flat config”) with TypeScript + React rules. - Ignored: - `dist/` - Rules include: - - `@eslint/js` - - `typescript-eslint` - - `eslint-plugin-react-hooks` + - `@eslint/js` + - `typescript-eslint` + - `eslint-plugin-react-hooks` - `eslint-plugin-react-refresh` (Vite) - + ## Authentication The API uses email + password login. - Users log in with **email** and **password**. @@ -217,3 +217,4 @@ Admins must be authenticated. User registration does not include email verification or “forgot password” functionality. - **No internationalization (i18n).** The client UI does not support multiple languages. + From 3168d7eccc1ad74412574308fbc6990f85e70a2a Mon Sep 17 00:00:00 2001 From: Jianming Fan <151937346+Jianming2024@users.noreply.github.com> Date: Thu, 18 Dec 2025 16:07:04 +0100 Subject: [PATCH 3/3] readme file format revised --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ee10e16..cfd2172 100644 --- a/README.md +++ b/README.md @@ -136,6 +136,7 @@ No token required: ### Authenticated user (role = Player or Admin) Users must be logged in (JWT required). + **Boards** - `GET /api/board/user/{userId}` (player = only own boards; admin = any user) @@ -165,6 +166,7 @@ Players must be authenticated. ### Admin only (role = Admin) Admins must be authenticated. + **Admin game management** - `POST /api/admin/games/draw` (trigger draw) - `GET /api/admin/games/draw/status` (view draw status) @@ -190,7 +192,7 @@ Admins must be authenticated. ![DBdeadpigeons.png](client/public/DBdeadpigeons.png) ## Deployment -** The backend is deployed using Docker and Fly.io. +**The backend is deployed using Docker and Fly.io.** - The API is built with a multi-stage Docker build - A lightweight ASP.NET runtime image is used in production - Deployed to Fly.io in the fra region @@ -204,7 +206,7 @@ Admins must be authenticated. - Frontend runs on http://localhost:5173 - API requests are proxied to the backend - CORS allows the local frontend origin - ** Production +**Production** - Frontend and backend are hosted separately - Backend is accessed over HTTPS via Fly.io - CORS allows only the production frontend domain