From fc06dac40ef0bfbbafb553e4daea9764b72fd08e Mon Sep 17 00:00:00 2001 From: "simon.franken" Date: Mon, 16 Feb 2026 17:12:47 +0100 Subject: [PATCH] update --- .env.docker | 5 +++++ .env.example | 17 ----------------- README.md | 11 +++++++++-- backend/src/config/index.ts | 2 +- backend/src/routes/auth.routes.ts | 4 ++-- docker-compose.yml | 10 ++++------ frontend/Dockerfile | 3 +++ frontend/src/api/auth.ts | 2 +- frontend/src/api/client.ts | 2 +- frontend/src/vite-env.d.ts | 13 +++++++++++++ frontend/vite.config.ts | 26 ++++++++++---------------- 11 files changed, 49 insertions(+), 46 deletions(-) create mode 100644 .env.docker delete mode 100644 .env.example create mode 100644 frontend/src/vite-env.d.ts diff --git a/.env.docker b/.env.docker new file mode 100644 index 0000000..7f790d8 --- /dev/null +++ b/.env.docker @@ -0,0 +1,5 @@ +APP_URL= +OIDC_ISSUER_URL= +OIDC_CLIENT_ID= +SESSION_SECRET= +API_URL= \ No newline at end of file diff --git a/.env.example b/.env.example deleted file mode 100644 index 8760f8f..0000000 --- a/.env.example +++ /dev/null @@ -1,17 +0,0 @@ -# Database -DATABASE_URL="postgresql://user:password@localhost:5432/timetracker" - -# OIDC Configuration -OIDC_ISSUER_URL="https://your-oidc-provider.com" -OIDC_CLIENT_ID="your-client-id" -OIDC_REDIRECT_URI="http://localhost:3000/auth/callback" - -# Session -SESSION_SECRET="your-session-secret-min-32-characters" - -# Server -PORT=3001 -NODE_ENV=development - -# Frontend URL (for CORS) -FRONTEND_URL="http://localhost:5173" \ No newline at end of file diff --git a/README.md b/README.md index 25af725..a902ad5 100644 --- a/README.md +++ b/README.md @@ -86,36 +86,41 @@ SESSION_SECRET="your-secure-session-secret-min-32-chars" # Server PORT=3001 NODE_ENV=development -FRONTEND_URL="http://localhost:5173" +APP_URL="http://localhost:5173" ``` ## API Endpoints ### Authentication + - `GET /auth/login` - Initiate OIDC login - `GET /auth/callback` - OIDC callback - `POST /auth/logout` - End session - `GET /auth/me` - Get current user ### Clients + - `GET /api/clients` - List clients - `POST /api/clients` - Create client - `PUT /api/clients/:id` - Update client - `DELETE /api/clients/:id` - Delete client ### Projects + - `GET /api/projects` - List projects - `POST /api/projects` - Create project - `PUT /api/projects/:id` - Update project - `DELETE /api/projects/:id` - Delete project ### Time Entries + - `GET /api/time-entries` - List entries (with filters/pagination) - `POST /api/time-entries` - Create entry - `PUT /api/time-entries/:id` - Update entry - `DELETE /api/time-entries/:id` - Delete entry ### Timer + - `GET /api/timer` - Get ongoing timer - `POST /api/timer/start` - Start timer - `PUT /api/timer` - Update timer (set project) @@ -134,6 +139,7 @@ User (oidc sub) ## Technology Stack **Backend:** + - Node.js + Express - TypeScript - Prisma ORM @@ -141,6 +147,7 @@ User (oidc sub) - OpenID Client **Frontend:** + - React 18 - TypeScript - TanStack Query @@ -150,4 +157,4 @@ User (oidc sub) ## License -MIT \ No newline at end of file +MIT diff --git a/backend/src/config/index.ts b/backend/src/config/index.ts index af1df43..b571f4b 100644 --- a/backend/src/config/index.ts +++ b/backend/src/config/index.ts @@ -25,7 +25,7 @@ export const config = { }, cors: { - origin: process.env.FRONTEND_URL || "http://localhost:5173", + origin: process.env.APP_URL || "http://localhost:5173", credentials: true, }, }; diff --git a/backend/src/routes/auth.routes.ts b/backend/src/routes/auth.routes.ts index 64b6f02..4516db7 100644 --- a/backend/src/routes/auth.routes.ts +++ b/backend/src/routes/auth.routes.ts @@ -62,11 +62,11 @@ router.get("/callback", async (req, res) => { delete req.session.oidc; // Redirect to frontend - const frontendUrl = process.env.FRONTEND_URL || "http://localhost:5173"; + const frontendUrl = process.env.APP_URL || "http://localhost:5173"; res.redirect(`${frontendUrl}/auth/callback?success=true`); } catch (error) { console.error("Callback error:", error); - const frontendUrl = process.env.FRONTEND_URL || "http://localhost:5173"; + const frontendUrl = process.env.APP_URL || "http://localhost:5173"; res.redirect(`${frontendUrl}/auth/callback?error=authentication_failed`); } }); diff --git a/docker-compose.yml b/docker-compose.yml index f398a1f..40c7f90 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,5 +1,3 @@ -version: '3.8' - services: db: image: postgres:16-alpine @@ -25,11 +23,11 @@ services: DATABASE_URL: "postgresql://timetracker:timetracker_password@db:5432/timetracker" OIDC_ISSUER_URL: ${OIDC_ISSUER_URL} OIDC_CLIENT_ID: ${OIDC_CLIENT_ID} - OIDC_REDIRECT_URI: "http://localhost:3001/api/auth/callback" + OIDC_REDIRECT_URI: "${API_URL}/auth/callback" SESSION_SECRET: ${SESSION_SECRET} PORT: 3001 NODE_ENV: production - FRONTEND_URL: "http://localhost:5173" + APP_URL: "${APP_URL}" ports: - "3001:3001" depends_on: @@ -40,8 +38,8 @@ services: build: context: ./frontend dockerfile: Dockerfile - environment: - VITE_API_URL: "http://localhost:3001" + args: + - VITE_API_URL=${API_URL} ports: - "5173:80" depends_on: diff --git a/frontend/Dockerfile b/frontend/Dockerfile index 9ceb444..2035016 100644 --- a/frontend/Dockerfile +++ b/frontend/Dockerfile @@ -1,6 +1,9 @@ # Build stage FROM node:20-alpine as builder +ARG VITE_API_URL +ENV VITE_API_URL=${VITE_API_URL} + WORKDIR /app COPY package*.json ./ diff --git a/frontend/src/api/auth.ts b/frontend/src/api/auth.ts index 26161d0..69473b1 100644 --- a/frontend/src/api/auth.ts +++ b/frontend/src/api/auth.ts @@ -1,7 +1,7 @@ import axios from "axios"; import type { User } from "@/types"; -const AUTH_BASE = "/api/auth"; +const AUTH_BASE = import.meta.env.VITE_API_URL + "/auth"; export const authApi = { login: (): void => { diff --git a/frontend/src/api/client.ts b/frontend/src/api/client.ts index f42e0d5..288efd4 100644 --- a/frontend/src/api/client.ts +++ b/frontend/src/api/client.ts @@ -1,7 +1,7 @@ import axios, { AxiosError } from "axios"; const apiClient = axios.create({ - baseURL: "/api", + baseURL: import.meta.env.VITE_API_URL, headers: { "Content-Type": "application/json", }, diff --git a/frontend/src/vite-env.d.ts b/frontend/src/vite-env.d.ts new file mode 100644 index 0000000..5da603e --- /dev/null +++ b/frontend/src/vite-env.d.ts @@ -0,0 +1,13 @@ +interface ViteTypeOptions { + // By adding this line, you can make the type of ImportMetaEnv strict + // to disallow unknown keys. + // strictImportMetaEnv: unknown +} + +interface ImportMetaEnv { + VITE_API_URL: string; +} + +interface ImportMeta { + readonly env: ImportMetaEnv; +} diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts index fd8dd49..cfbcb29 100644 --- a/frontend/vite.config.ts +++ b/frontend/vite.config.ts @@ -2,22 +2,16 @@ import { defineConfig } from "vite"; import react from "@vitejs/plugin-react"; import path from "path"; -const backend = "http://127.0.0.1:3001"; - -export default defineConfig({ - plugins: [react()], - resolve: { - alias: { - "@": path.resolve(__dirname, "./src"), - }, - }, - server: { - port: 5173, - proxy: { - "/api": { - target: backend, - changeOrigin: true, +export default defineConfig(() => { + return { + plugins: [react()], + resolve: { + alias: { + "@": path.resolve(__dirname, "./src"), }, }, - }, + server: { + port: 5173, + }, + }; });