diff --git a/README.md b/README.md index 8bd44e5..79c6bd0 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,15 @@ -# MCS Lose +# MCS TicketHub -A small full-stack demo app to manage "Lose" entries (Losnummer records) using a React + TypeScript frontend, an Express (Node) backend, and a MySQL database. The project is containerised with Docker Compose for easy local development. +[![Node.js](https://img.shields.io/badge/Node.js-%23339933?logo=node.js&logoColor=white)](https://nodejs.org/) +[![Express](https://img.shields.io/badge/Express-%236a6a6a?logo=express&logoColor=white)](https://expressjs.com/) +[![React](https://img.shields.io/badge/React-%2361DAFB?logo=react&logoColor=black)](https://reactjs.org/) +[![TypeScript](https://img.shields.io/badge/TypeScript-%23007ACC?logo=typescript&logoColor=white)](https://www.typescriptlang.org/) +[![Vite](https://img.shields.io/badge/Vite-%23646CFF?logo=vite&logoColor=white)](https://vitejs.dev/) +[![MySQL](https://img.shields.io/badge/MySQL-%2300758F?logo=mysql&logoColor=white)](https://www.mysql.com/) +[![Docker](https://img.shields.io/badge/Docker-%230db7ed?logo=docker&logoColor=white)](https://www.docker.com/) +[![Tailwind CSS](https://img.shields.io/badge/Tailwind%20CSS-%2338B2AC?logo=tailwindcss&logoColor=white)](https://tailwindcss.com/) + +MCS TicketHub — my first project. I intend to sell this application. The app manages "Losnummer" (ticket) records: a React + TypeScript frontend provides CSV import, table view, and row editing; an Express backend exposes REST endpoints and JWT-protected admin actions; data is persisted in a MySQL `lose` table. The project is containerised with Docker Compose for easy local development. ## Quick overview @@ -15,58 +24,6 @@ A small full-stack demo app to manage "Lose" entries (Losnummer records) using a - Allow admins to login and perform protected operations (create, delete, update rows). - Keep the setup easy to run locally via Docker. -## Prerequisites - -- Docker & Docker Compose (tested on macOS in this workspace). -- Alternatively, Node 18+ and npm/yarn to run services locally without containers. - -## Quick start (recommended: Docker) - -Start backend + MySQL using Docker Compose: - -```zsh -docker compose up -d --build -``` - -Stop and remove containers: - -```zsh -docker compose down -``` - -The backend will be available at http://localhost:8002 by default (see `docker-compose.yml`). MySQL is exposed on host port 3308 -> container 3306. - -## Running services locally (without Docker) - -Backend - -```zsh -cd backend -npm install -# set env vars (see Environment section) or create a .env file -npm start -``` - -Frontend - -```zsh -cd frontend -npm install -npm run dev -``` - -## Environment variables - -The backend reads configuration from environment variables (some are present in `docker-compose.yml`): - -- DB_HOST - MySQL host (e.g. `mysql` in compose) -- DB_USER - MySQL user (`root` in compose) -- DB_PASSWORD - MySQL root password -- DB_NAME - MySQL database name (e.g. `mcs_lose`) -- SECRET_KEY - secret used to sign JWT tokens (required for authentication) - -Important: do not commit secrets to source control. In production, provide `SECRET_KEY` through a secure secret manager. - ## API (backend) All endpoints are served by the Express backend in `backend/server.js`. @@ -103,6 +60,8 @@ Notes: - The current SQL uses simple types and a single `losnummer` unique constraint. Consider adding an auto-increment id column if needed. +You can also see the database schema in `backend/scheme.sql`. + ## Project structure (high level) - backend/ @@ -119,32 +78,6 @@ Notes: - docker-compose.yml — config for backend and MySQL containers -## Notable implementation details & known issues +## Commercial intent -- Body size limits are increased in `server.js` to accept large CSV/JSON payloads (limit: 10mb). -- Passwords for `admin_user` are stored and checked as plaintext in `database.js` — this is insecure. Use salted password hashing (bcrypt) for real deployments. -- `tokenService.js` currently logs the generated token to console — remove that in production. -- `getTableData()` in `services/database.js` has an incorrect code path checking `result.entries.length` (should check `result.length`). This may cause unexpected behavior when the table is empty. -- Queries use parameterized queries with `mysql2` which protects against SQL injection for provided query parameters. - -## Suggestions / TODOs - -- Fix the `getTableData()` empty-check bug. -- Hash admin passwords and add a registration/migration path for admin accounts. -- Add input validation on API endpoints and better error handling/user feedback. -- Consider adding database migrations (Flyway, knex, sequelize migrations). -- Add tests and CI for backend endpoints. -- Optionally enable the frontend service in `docker-compose.yml` (it's currently commented out). - -## Development tips - -- To inspect the MySQL data created by Docker Compose, you can connect with your preferred MySQL client to `localhost:3308` (user and password from `docker-compose.yml`). -- To generate a token from the backend for testing, create an admin user entry in `admin_user` and POST to `/login`. - -## License - -No license specified. Add a LICENSE file if you want to open-source this project. - -## Contacts / credits - -Project created in this workspace. See `backend` and `frontend` folders for authorship and details. +The project owner intends to sell this application commercially. If you are interested in licensing or purchasing the application, add contact details or a sales/licensing process to this README or repository metadata.