From 54cc4ea697bc132eb64d7b4d654c6720b74fb665 Mon Sep 17 00:00:00 2001 From: chad Date: Sat, 4 Oct 2025 10:41:29 -0400 Subject: [PATCH] readme update --- README.md | 128 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 127 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index dcc515e..435251e 100644 --- a/README.md +++ b/README.md @@ -1 +1,127 @@ -# ECS FULL STACK \ No newline at end of file +# ECS Full Stack + +A full-stack example project that integrates a React frontend, an Express backend, and a Discord bot. The app provides a dashboard for server admins to manage bot settings and invites, plus Discord moderation/integration features via a bot running with discord.js. + +This README documents how to get the project running, what environment variables are required, where to get Discord keys, how the invite token flow works, and basic troubleshooting tips. + +## Repository layout + +- `frontend/` — React (Create React App) frontend. Uses `REACT_APP_API_BASE` to communicate with the backend in dev and production. +- `backend/` — Express backend and API server that also coordinates with the `discord-bot` library to manage guilds, invites, and settings. Uses environment variables for configuration. +- `discord-bot/` — small wrapper that logs the bot in and exposes the discord.js client used by the backend. +- `checklist.md`, `README.md`, other docs and small scripts at repo root. + +## What this project does + +- Provides a React dashboard where a user can view servers the bot is connected to and manage per-server settings (welcome/leave messages, autorole, toggling commands, invite creation/listing/deletion). +- Runs a Discord bot (discord.js) that performs moderation and server features. The backend and bot are closely integrated: the backend hosts the API and the bot client is shared to fetch guild data and manipulate invites/channels/roles. +- Uses a short-lived token flow to authorize invite deletions from the frontend without embedding long-lived secrets in the client. + +## Quickstart — prerequisites + +- Node.js (recommended 18.x or later) and npm +- A Discord application with a Bot user (to get `DISCORD_CLIENT_ID` and `DISCORD_CLIENT_SECRET`) — see below for setup steps +- Optional: a VPS or Tailscale IP if you want to run the frontend/backend on a non-localhost address + +## Environment configuration (.env) + +There are env files used by the backend and frontend. Create `.env` files in the `backend/` and `frontend/` folders for local development. Examples follow. + +### backend/.env (example) + +PORT=3002 +HOST=0.0.0.0 +BACKEND_BASE=http://your-server-or-ip:3002 +FRONTEND_BASE=http://your-server-or-ip:3001 +CORS_ORIGIN=http://your-server-or-ip:3001 +DISCORD_CLIENT_ID=your_discord_client_id +DISCORD_CLIENT_SECRET=your_discord_client_secret +ENCRYPTION_KEY=a-32-byte-or-longer-secret +INVITE_TOKEN_SECRET=optional-second-secret-for-invite-tokens + +- `PORT` / `HOST`: where the backend listens. +- `BACKEND_BASE` and `FRONTEND_BASE`: used for constructing OAuth redirect URIs and links. +- `CORS_ORIGIN`: optional; set to your frontend origin to restrict CORS. +- `DISCORD_CLIENT_ID` / `DISCORD_CLIENT_SECRET`: from the Discord Developer Portal (see below). +- `ENCRYPTION_KEY` or `INVITE_TOKEN_SECRET`: used to sign short-lived invite tokens. Keep this secret. + +Note: This project previously supported an `INVITE_API_KEY` static secret; that requirement has been removed. Invite deletes are authorized via short-lived invite tokens by default. + +### frontend/.env (example) + +HOST=0.0.0.0 +PORT=3001 +REACT_APP_API_BASE=http://your-server-or-ip:3002 + +Set `REACT_APP_API_BASE` to point at the backend so the frontend can call API endpoints. + +## Create a Discord Application and Bot (short) + +1. Go to the Discord Developer Portal: https://discord.com/developers/applications +2. Create a new application. +3. Under "OAuth2" -> "General", add your redirect URI: + - For dev: `http://your-server-or-ip:3002/auth/discord/callback` + - Make sure `BACKEND_BASE` matches the host/port you set in `backend/.env`. +4. Under "Bot" create a Bot user and copy the Bot token (NOT committed to source). +5. Under "OAuth2" -> "URL Generator" select scopes `bot` and `applications.commands` and select permissions (e.g., Administrator if you want full access for testing). Use the generated URL to invite the bot to your guild during testing. + +Store the Client ID / Client Secret in your `backend/.env` as `DISCORD_CLIENT_ID` and `DISCORD_CLIENT_SECRET`. + +## Invite token flow (why and how) + +- To avoid embedding long-lived secrets in a web client, invite deletions are authorized with a short-lived HMAC-signed token. +- The frontend requests a token with: + GET /api/servers/:guildId/invite-token +- The backend returns `{ token: '...' }`. The frontend then calls + DELETE /api/servers/:guildId/invites/:code + with header `x-invite-token: ` +- Token TTL is short (default 5 minutes) and is signed using `INVITE_TOKEN_SECRET` or `ENCRYPTION_KEY` from backend `.env`. + +Security note: Currently the `/invite-token` endpoint issues tokens to any caller. For production you should restrict this endpoint by requiring OAuth authentication and checking that the requesting user is authorized for the target guild. + +## Run the app locally + +1. Backend + +```powershell +cd backend +npm install +# create backend/.env from the example above +npm start +``` + +2. Frontend + +```powershell +cd frontend +npm install +# create frontend/.env with REACT_APP_API_BASE pointing to the backend +npm run start +``` + +3. Discord bot + +- The backend boots the bot client (see `discord-bot/`), so if the backend is started and credentials are correct, the bot will log in and register slash commands. You can also run the `discord-bot` project separately if you prefer. + +## Troubleshooting + +- Backend refuses to start or missing package.json: ensure you run `npm install` in the `backend` folder and run `npm start` from that folder. +- CORS errors: verify `CORS_ORIGIN` and `REACT_APP_API_BASE` match your frontend origin. +- Invite delete unauthorized: ensure backend `INVITE_TOKEN_SECRET` or `ENCRYPTION_KEY` is present and token TTL has not expired. Check the backend logs for validation details. +- Token issues: clock skew can cause tokens to appear expired — ensure server and client clocks are reasonably in sync. + +## Developer notes + +- The dashboard UI is in `frontend/src/components/` (notable files: `Dashboard.js`, `ServerSettings.js`, `Login.js`). +- The Express API is in `backend/index.js` and uses `discord-bot` (discord.js client) to operate on guilds, invites, channels and roles. +- Invite delete flow: frontend fetches a short-lived token then requests DELETE with header `x-invite-token`. + +## Next steps / suggestions + +- Harden `/api/servers/:guildId/invite-token` to require an authenticated user and verify the user has admin permissions for the guild. +- Add rate-limiting to token issuance and optionally keep the old `INVITE_API_KEY` option for server-to-server automation. + +If you want, I can add step-by-step instructions to create the `.env` files from templates, or implement the production safe option of authenticating `/invite-token` requests. Tell me which you'd prefer. + +--- +Updated: Oct 4, 2025 \ No newline at end of file