From cdbf1e42778143b07c01879e4b2ba84e829a7cc0 Mon Sep 17 00:00:00 2001 From: Tein Schoemaker Date: Wed, 17 Sep 2025 21:03:56 +0200 Subject: [PATCH 1/6] Hardcoded is no no --- src/components/cohortlist/index.js | 3 ++- src/components/searchResults/index.js | 3 ++- src/pages/dashboard/index.js | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/components/cohortlist/index.js b/src/components/cohortlist/index.js index 46ee095..04daef5 100644 --- a/src/components/cohortlist/index.js +++ b/src/components/cohortlist/index.js @@ -3,6 +3,7 @@ import ProfileCircle from '../profileCircle'; import { PiDotsThree } from 'react-icons/pi'; import './style.css'; import { cohort } from '../../service/mockData'; +import { API_URL } from '../../service/constants'; const CohortList = ({ cohortId, userId }) => { const [users, setUsers] = useState([]); @@ -11,7 +12,7 @@ const CohortList = ({ cohortId, userId }) => { useEffect(() => { setLoading(true); if (cohortId) { - fetch(`https://localhost:7233/users/by_cohort/${cohortId}`) + fetch(`${API_URL}/users/by_cohort/${cohortId}`) .then((res) => res.json()) .then((data) => { setUsers(data.data.users); diff --git a/src/components/searchResults/index.js b/src/components/searchResults/index.js index 3b71997..1491b23 100644 --- a/src/components/searchResults/index.js +++ b/src/components/searchResults/index.js @@ -3,6 +3,7 @@ import TextInput from '../form/textInput'; import ProfileCircle from '../profileCircle'; import SearchIcon from '../../assets/icons/searchIcon'; import './style.css'; +import { API_URL } from '../../service/constants'; const SearchResults = () => { const [searchVal, setSearchVal] = useState(''); @@ -13,7 +14,7 @@ const SearchResults = () => { if (searchVal.trim().length >= 3) { setLoading(true); const timer = setTimeout(() => { - fetch(`https://localhost:7233/users?searchTerm=${encodeURIComponent(searchVal)}`) + fetch(`${API_URL}/users?searchTerm=${encodeURIComponent(searchVal)}`) .then((res) => res.json()) .then((data) => setSearchResults(data.data.users)) .catch(() => setSearchResults([])) diff --git a/src/pages/dashboard/index.js b/src/pages/dashboard/index.js index 23e1266..fbf2bdf 100644 --- a/src/pages/dashboard/index.js +++ b/src/pages/dashboard/index.js @@ -10,6 +10,7 @@ import jwtDecode from 'jwt-decode'; import SearchResults from '../../components/searchResults'; import TeacherUserlist from '../../components/TeacherUserlist'; import useAuth from '../../hooks/useAuth'; +import { API_URL } from '../../service/constants'; const Dashboard = () => { const [cohortId, setCohortId] = useState(null); @@ -17,7 +18,7 @@ const Dashboard = () => { const decodedToken = jwtDecode(storedToken); const userId = decodedToken['http://schemas.xmlsoap.org/ws/2005/05/identity/claims/sid']; const userRole = decodedToken['http://schemas.microsoft.com/ws/2008/06/identity/claims/role']; - const userURL = `https://localhost:7233/users/`; + const userURL = `${API_URL}/users/`; const { loggedInUser } = useAuth(); useEffect(() => { From da6fa09523572f426ebacc6db63e90fcd460c2d1 Mon Sep 17 00:00:00 2001 From: Tein Schoemaker Date: Fri, 19 Sep 2025 15:09:23 +0200 Subject: [PATCH 2/6] Docker? --- .dockerignore | 22 ++++++++++++++++++++++ Dockerfile | 29 +++++++++++++++++++++++++++++ docker-compose.yml | 10 ++++++++++ nginx.conf | 15 +++++++++++++++ 4 files changed, 76 insertions(+) create mode 100644 .dockerignore create mode 100644 Dockerfile create mode 100644 docker-compose.yml create mode 100644 nginx.conf diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..fb764bc --- /dev/null +++ b/.dockerignore @@ -0,0 +1,22 @@ +# Dependencies +node_modules +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* + +# Build output +build +dist + +# Local env files +.env* + +# VCS +.git +.gitignore + +# Editor/OS +.DS_Store +.vscode +Thumbs.db \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..b63fb5e --- /dev/null +++ b/Dockerfile @@ -0,0 +1,29 @@ + +FROM node:20-alpine AS builder + +WORKDIR /app + + +COPY package*.json ./ + +RUN npm ci --no-audit --no-fund || npm install --no-audit --no-fund + + +COPY . . + +ARG REACT_APP_API_URL + +ENV REACT_APP_API_URL=$REACT_APP_API_URL + +RUN npm run build + + +FROM nginx:alpine + +COPY nginx.conf /etc/nginx/conf.d/default.conf + +COPY --from=builder /app/build /usr/share/nginx/html + +EXPOSE 80 + +CMD ["nginx", "-g", "daemon off;"] \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..a960cfd --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,10 @@ +services: + web: + build: + context: . + dockerfile: Dockerfile + args: + REACT_APP_API_URL: "http://localhost:3001" + image: team-dev-client:web + ports: + - "3000:80" \ No newline at end of file diff --git a/nginx.conf b/nginx.conf new file mode 100644 index 0000000..60a677e --- /dev/null +++ b/nginx.conf @@ -0,0 +1,15 @@ +server { + listen 80; + server_name _; + + root /usr/share/nginx/html; + index index.html; + + location / { + try_files $uri /index.html; + } + + gzip on; + gzip_types text/plain application/javascript application/x-javascript text/javascript text/xml text/css application/json image/svg+xml; + gzip_min_length 256; +} From a82f4b26ad1eb5587a78cdf99cff4790b523bba9 Mon Sep 17 00:00:00 2001 From: Tein Schoemaker Date: Tue, 23 Sep 2025 15:57:32 +0200 Subject: [PATCH 3/6] Whoa! Docker compose? --- docker-compose.yml | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index a960cfd..7c6319f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,4 +1,31 @@ services: + db: + image: postgres:16-alpine + environment: + - POSTGRES_USER=appuser + - POSTGRES_PASSWORD=apppassword + - POSTGRES_DB=appdb + ports: + - "5434:5432" + volumes: + - pgdata:/var/lib/postgresql/data + + api: + build: + context: ../csharp-team-dev-server-team-4/exercise.wwwapi + dockerfile: Dockerfile + image: team-dev-api + environment: + - ConnectionStrings__DefaultConnection=Host=db;Port=5432;Database=appdb;Username=appuser;Password=apppassword;SSL Mode=Disable + - Token="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/" + - JWT__SigningKey=dev-super-secret-signing-key + - ASPNETCORE_ENVIRONMENT=Development + - ASPNETCORE_URLS=http://+:8080 + ports: + - "3001:8080" + depends_on: + - db + web: build: context: . @@ -7,4 +34,9 @@ services: REACT_APP_API_URL: "http://localhost:3001" image: team-dev-client:web ports: - - "3000:80" \ No newline at end of file + - "3000:80" + depends_on: + - api + +volumes: + pgdata: \ No newline at end of file From 23337e92b9ace20a03c88813e7877d794632f379 Mon Sep 17 00:00:00 2001 From: Tein Schoemaker Date: Wed, 24 Sep 2025 22:21:34 +0200 Subject: [PATCH 4/6] Team integration --- .env.example | 26 +++++++++++++++++++++++++- README.md | 2 ++ docker-compose.yml | 32 ++++++++++++++++---------------- 3 files changed, 43 insertions(+), 17 deletions(-) diff --git a/.env.example b/.env.example index e67d4e5..121d31e 100644 --- a/.env.example +++ b/.env.example @@ -1 +1,25 @@ -REACT_APP_API_URL="http://localhost:4000" \ No newline at end of file +# Copy this file to .env and adjust token values + +POSTGRES_USER=appuser +POSTGRES_PASSWORD=apppassword +POSTGRES_DB=appdb +DB_PORT=5434 + +# Expecting server project in same parent folder as client +API_BUILD_CONTEXT=../csharp-team-dev-server-team-4/exercise.wwwapi +API_DOCKERFILE=Dockerfile + +API_IMAGE_NAME=team-dev-api +API_PORT=3001 +ASPNETCORE_ENVIRONMENT=Development +ASPNETCORE_URLS=http://+:8080 +# Generate a secure random key (openssl rand -hex 32) for production use +JWT_SIGNING_KEY=dev-super-secret-signing-key +API_TOKEN=dev-token-please-change + +WEB_IMAGE_NAME=team-dev-client:web +WEB_PORT=3000 + +REACT_APP_API_URL=http://localhost:3001 + +COMPOSE_PROJECT_NAME=team-dev \ No newline at end of file diff --git a/README.md b/README.md index 60494ec..e10cd9e 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,8 @@ Client repository for team dev project. 2. Make sure the `REACT_APP_API_URL` environment variable in the `.env` file contains the URL of the server app on your machine 3. `npm ci` to install dependencies 4. `npm start` to run the app. The server must also be running on your machine +5. `docker compose up --build` to start up the docker containers for use +6. `docker compose down` to stop running docker ### Project Management diff --git a/docker-compose.yml b/docker-compose.yml index 7c6319f..f812d5e 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,27 +2,27 @@ services: db: image: postgres:16-alpine environment: - - POSTGRES_USER=appuser - - POSTGRES_PASSWORD=apppassword - - POSTGRES_DB=appdb + - POSTGRES_USER=${POSTGRES_USER:-appuser} + - POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-apppassword} + - POSTGRES_DB=${POSTGRES_DB:-appdb} ports: - - "5434:5432" + - "${DB_PORT:-5434}:5432" volumes: - pgdata:/var/lib/postgresql/data api: build: - context: ../csharp-team-dev-server-team-4/exercise.wwwapi - dockerfile: Dockerfile - image: team-dev-api + context: ${API_BUILD_CONTEXT:-../csharp-team-dev-server-team-4/exercise.wwwapi} + dockerfile: ${API_DOCKERFILE:-Dockerfile} + image: ${API_IMAGE_NAME:-team-dev-api} environment: - - ConnectionStrings__DefaultConnection=Host=db;Port=5432;Database=appdb;Username=appuser;Password=apppassword;SSL Mode=Disable - - Token="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/" - - JWT__SigningKey=dev-super-secret-signing-key - - ASPNETCORE_ENVIRONMENT=Development - - ASPNETCORE_URLS=http://+:8080 + - ConnectionStrings__DefaultConnection=Host=db;Port=5432;Database=${POSTGRES_DB:-appdb};Username=${POSTGRES_USER:-appuser};Password=${POSTGRES_PASSWORD:-apppassword};SSL Mode=Disable + - Token=${API_TOKEN:-dev-token-please-change} + - JWT__SigningKey=${JWT_SIGNING_KEY:-dev-super-secret-signing-key} + - ASPNETCORE_ENVIRONMENT=${ASPNETCORE_ENVIRONMENT:-Development} + - ASPNETCORE_URLS=${ASPNETCORE_URLS:-http://+:8080} ports: - - "3001:8080" + - "${API_PORT:-3001}:8080" depends_on: - db @@ -31,10 +31,10 @@ services: context: . dockerfile: Dockerfile args: - REACT_APP_API_URL: "http://localhost:3001" - image: team-dev-client:web + REACT_APP_API_URL: ${REACT_APP_API_URL:-http://localhost:${API_PORT:-3001}} + image: ${WEB_IMAGE_NAME:-team-dev-client:web} ports: - - "3000:80" + - "${WEB_PORT:-3000}:80" depends_on: - api From 4880ae82c2da02dbb734508bd30a747aef04830e Mon Sep 17 00:00:00 2001 From: Tein Schoemaker Date: Mon, 29 Sep 2025 10:23:38 +0200 Subject: [PATCH 5/6] Demo ready --- .env.example | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/.env.example b/.env.example index 121d31e..50d6a99 100644 --- a/.env.example +++ b/.env.example @@ -1,11 +1,13 @@ -# Copy this file to .env and adjust token values +## Setup: copy this file to .env then run: docker compose up --build -d +## Replace API_TOKEN & JWT_SIGNING_KEY with secure random keys (>64 bytes for HS512). +## Generate command: openssl rand -hex 96 POSTGRES_USER=appuser POSTGRES_PASSWORD=apppassword POSTGRES_DB=appdb DB_PORT=5434 -# Expecting server project in same parent folder as client +# Server project expected in sibling folder to this client repo API_BUILD_CONTEXT=../csharp-team-dev-server-team-4/exercise.wwwapi API_DOCKERFILE=Dockerfile @@ -13,9 +15,9 @@ API_IMAGE_NAME=team-dev-api API_PORT=3001 ASPNETCORE_ENVIRONMENT=Development ASPNETCORE_URLS=http://+:8080 -# Generate a secure random key (openssl rand -hex 32) for production use -JWT_SIGNING_KEY=dev-super-secret-signing-key -API_TOKEN=dev-token-please-change +# HS512 signing keys must be >64 bytes. Replace these dev values. +JWT_SIGNING_KEY=change-me-jwt-signing-key-min-65-bytes +API_TOKEN=change-me-api-token-min-65-bytes WEB_IMAGE_NAME=team-dev-client:web WEB_PORT=3000 From 63ee270e68493286618c19d5c224f0f78adfca11 Mon Sep 17 00:00:00 2001 From: Tein Schoemaker Date: Mon, 29 Sep 2025 12:53:26 +0200 Subject: [PATCH 6/6] Demo --- Dockerfile | 2 +- nginx.conf | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index b63fb5e..921d5a6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -24,6 +24,6 @@ COPY nginx.conf /etc/nginx/conf.d/default.conf COPY --from=builder /app/build /usr/share/nginx/html -EXPOSE 80 +EXPOSE 8080 CMD ["nginx", "-g", "daemon off;"] \ No newline at end of file diff --git a/nginx.conf b/nginx.conf index 60a677e..d0de181 100644 --- a/nginx.conf +++ b/nginx.conf @@ -1,5 +1,5 @@ server { - listen 80; + listen 8080; server_name _; root /usr/share/nginx/html;