update
This commit is contained in:
5
.env.docker
Normal file
5
.env.docker
Normal file
@@ -0,0 +1,5 @@
|
||||
APP_URL=
|
||||
OIDC_ISSUER_URL=
|
||||
OIDC_CLIENT_ID=
|
||||
SESSION_SECRET=
|
||||
API_URL=
|
||||
17
.env.example
17
.env.example
@@ -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"
|
||||
11
README.md
11
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
|
||||
MIT
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -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`);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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 ./
|
||||
|
||||
@@ -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 => {
|
||||
|
||||
@@ -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",
|
||||
},
|
||||
|
||||
13
frontend/src/vite-env.d.ts
vendored
Normal file
13
frontend/src/vite-env.d.ts
vendored
Normal file
@@ -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;
|
||||
}
|
||||
@@ -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,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user