refactor: remove all JWT-related code and references

JWT was never used - auth uses X-User-Id header. Removes jwt.ts utility,
jsonwebtoken dependency, stubbed refresh/logout endpoints, and updates
all docs (PUML diagrams, api-routes, tex, CLAUDE.md) accordingly.
This commit is contained in:
2026-02-09 20:02:05 +01:00
parent cb32bd23ca
commit 73e768a0ad
12 changed files with 10 additions and 179 deletions

View File

@@ -48,7 +48,7 @@ npm run start -w @calchat/server # Run compiled server (port 3000)
| | MongoDB | Database |
| | Mongoose | ODM |
| | GPT (OpenAI) | AI/LLM for chat |
| | X-User-Id Header | Authentication (simple, no JWT yet) |
| | X-User-Id Header | Authentication |
| | pino / pino-http | Structured logging |
| | react-native-logs | Client-side logging |
| | tsdav | CalDAV client library |
@@ -235,7 +235,7 @@ CardBase
src/
├── app.ts # Entry point, DI setup, Express config
├── controllers/ # Request handlers + middleware (per architecture diagram)
│ ├── AuthController.ts # login(), register(), refresh(), logout()
│ ├── AuthController.ts # login(), register()
│ ├── ChatController.ts # sendMessage(), confirmEvent() + CalDAV push, rejectEvent(), getConversations(), getConversation(), updateProposalEvent()
│ ├── EventController.ts # create(), getById(), getAll(), getByDateRange(), update(), delete() - pushes/deletes to CalDAV on mutations
│ ├── CaldavController.ts # saveConfig(), loadConfig(), deleteConfig(), pullEvents(), pushEvents(), pushEvent()
@@ -285,7 +285,6 @@ src/
│ ├── toolDefinitions.ts # TOOL_DEFINITIONS - provider-agnostic tool specs
│ └── toolExecutor.ts # executeToolCall() - handles getDay, proposeCreate/Update/Delete, searchEvents, getEventsInRange
├── utils/
│ ├── jwt.ts # signToken(), verifyToken() - NOT USED YET (no JWT)
│ ├── password.ts # hash(), compare() using bcrypt
│ ├── eventFormatters.ts # getWeeksOverview(), getMonthOverview() - formatted event listings
│ └── recurrenceExpander.ts # expandRecurringEvents() - expand recurring events into occurrences
@@ -296,8 +295,6 @@ src/
**API Endpoints:**
- `POST /api/auth/login` - User login
- `POST /api/auth/register` - User registration
- `POST /api/auth/refresh` - Refresh JWT token
- `POST /api/auth/logout` - User logout
- `GET /api/events` - Get all events (protected)
- `GET /api/events/range` - Get events by date range (protected)
- `GET /api/events/:id` - Get single event (protected)
@@ -536,8 +533,6 @@ docker compose up -d # Start Radicale CalDAV server
### Environment Variables
Server requires `.env` file in `apps/server/`:
```
JWT_SECRET=your-secret-key
JWT_EXPIRES_IN=1h
MONGODB_URI=mongodb://root:mongoose@localhost:27017/calchat?authSource=admin
OPENAI_API_KEY=sk-proj-...
USE_TEST_RESPONSES=false # true = static test responses, false = real GPT AI
@@ -585,10 +580,6 @@ NODE_ENV=development # development = pretty logs, production = JSON
- `EventService`: Extended with searchByTitle(), findByCaldavUUID()
- `utils/eventFormatters`: Refactored to use EventService instead of EventRepository
- CORS configured to allow X-User-Id header
- **Stubbed (TODO):**
- `AuthController`: refresh(), logout()
- `AuthService`: refreshToken()
- JWT authentication (currently using simple X-User-Id header)
**Shared:**
- Types, DTOs, constants (Day, Month with German translations), ExpandedEvent type, CaldavConfig, CaldavSyncStatus defined and exported

View File

@@ -14,7 +14,6 @@
"dotenv": "^16.4.7",
"express": "^5.2.1",
"ical.js": "^2.2.1",
"jsonwebtoken": "^9.0.3",
"mongoose": "^9.1.1",
"openai": "^6.15.0",
"pino": "^10.1.1",
@@ -27,7 +26,6 @@
"@types/express": "^5.0.6",
"@types/ical": "^0.8.3",
"@types/jest": "^30.0.0",
"@types/jsonwebtoken": "^9.0.10",
"@types/node": "^24.10.1",
"jest": "^30.2.0",
"pino-pretty": "^13.1.3",

View File

@@ -22,11 +22,4 @@ export class AuthController {
}
}
async refresh(req: Request, res: Response): Promise<void> {
throw new Error("Not implemented");
}
async logout(req: Request, res: Response): Promise<void> {
throw new Error("Not implemented");
}
}

View File

@@ -6,8 +6,6 @@ export function createAuthRoutes(authController: AuthController): Router {
router.post("/login", (req, res) => authController.login(req, res));
router.post("/register", (req, res) => authController.register(req, res));
router.post("/refresh", (req, res) => authController.refresh(req, res));
router.post("/logout", (req, res) => authController.logout(req, res));
return router;
}

View File

@@ -1,6 +1,5 @@
import { User, CreateUserDTO, LoginDTO, AuthResponse } from "@calchat/shared";
import { CreateUserDTO, LoginDTO, AuthResponse } from "@calchat/shared";
import { UserRepository } from "./interfaces";
import * as jwt from "../utils/jwt";
import * as password from "../utils/password";
export class AuthService {
@@ -46,11 +45,4 @@ export class AuthService {
return { user, accessToken: "" };
}
async refreshToken(refreshToken: string): Promise<AuthResponse> {
throw new Error("Not implemented");
}
async logout(userId: string): Promise<void> {
throw new Error("Not implemented");
}
}

View File

@@ -1,2 +1 @@
export * from "./jwt";
export * from "./password";

View File

@@ -1,26 +0,0 @@
import jwt from "jsonwebtoken";
export interface TokenPayload {
userId: string;
email: string;
}
export interface JWTConfig {
secret: string;
expiresIn: string;
}
const JWT_SECRET = process.env.JWT_SECRET || "your-secret-key";
const JWT_EXPIRES_IN = process.env.JWT_EXPIRES_IN || "1h";
export function signToken(payload: TokenPayload): string {
throw new Error("Not implemented");
}
export function verifyToken(token: string): TokenPayload {
throw new Error("Not implemented");
}
export function decodeToken(token: string): TokenPayload | null {
throw new Error("Not implemented");
}

View File

@@ -11,15 +11,13 @@ Base URL: `/api`
|--------|----------|--------------|
| POST | `/auth/login` | User Login |
| POST | `/auth/register` | User Registrierung |
| POST | `/auth/refresh` | JWT Token erneuern |
| POST | `/auth/logout` | User Logout |
---
## Events
### Event Endpoints (`/api/events`)
Alle Endpoints erfordern JWT-Authentifizierung.
Alle Endpoints erfordern Authentifizierung (X-User-Id Header).
| Method | Endpoint | Beschreibung |
|--------|----------|--------------|
@@ -35,7 +33,7 @@ Alle Endpoints erfordern JWT-Authentifizierung.
## Chat
### Chat Endpoints (`/api/chat`)
Alle Endpoints erfordern JWT-Authentifizierung.
Alle Endpoints erfordern Authentifizierung (X-User-Id Header).
| Method | Endpoint | Beschreibung |
|--------|----------|--------------|

View File

@@ -188,11 +188,6 @@ package "Models" #D3D3D3 {
}
package "Utils" #DDA0DD {
class JWT {
' +signToken()
' +verifyToken()
}
class Password {
' +hash()
' +compare()
@@ -215,8 +210,6 @@ ChatController --> CaldavService
EventController --> EventService
EventController --> CaldavService
CaldavController --> CaldavService
AuthMiddleware --> JWT
' Service -> Interfaces (intern)
AuthService --> UserRepository
ChatService --> ChatRepository
@@ -227,7 +220,6 @@ CaldavService --> CaldavRepository
CaldavService --> EventService
' Auth uses Utils
AuthService --> JWT
AuthService --> Password
' Event/Chat uses Utils

View File

@@ -77,7 +77,6 @@ package "apps/server (Express.js)" as ServerPkg #98FB98 {
}
package "Utils" {
[JWT] as JWTUtil
[Password] as PwdUtil
[RecurrenceExpander] as RecExpander
[EventFormatters] as EvtFormatters
@@ -154,9 +153,7 @@ GPT ..|> Interfaces
Repos ..|> Interfaces
' Backend: Service -> Utils
AuthSvc --> JWTUtil
AuthSvc --> PwdUtil
Middleware --> JWTUtil
EventSvc --> RecExpander
ChatSvc --> EvtFormatters

View File

@@ -66,7 +66,7 @@ Backend & Express.js & Web-App Framework \\
& MongoDB & Datenbank \\
& Mongoose & ODM \\
& Claude (Anthropic) & KI / LLM \\
& JWT & Authentifizierung \\
& X-User-Id Header & Authentifizierung \\
\hline
Geplant & iCalendar & Event-Export \\
\hline
@@ -112,8 +112,9 @@ Der wichtigste Teil der App ist die KI-Integration über \textbf{Claude}
(Anthropic). Dieses LLM verarbeitet natürlichsprachliche Eingaben der Nutzer und
generiert daraus strukturierte Event-Vorschläge.
Die Authentifizierung läuft über \textbf{JSON Web Tokens} (JWT). Der Vorteil:
zustandslose Sessions, bei denen der Server keine Session-Daten speichern muss.
Die Authentifizierung erfolgt über einen \textbf{X-User-Id Header}, der bei
jedem Request die User-ID mitschickt. Diese einfache Lösung reicht für den
aktuellen Entwicklungsstand aus.
Geplant ist außerdem die Unterstützung des \textbf{iCalendar}-Formats (ICAL)
für den Export von Kalender-Events.
@@ -157,7 +158,7 @@ Notiz-Feld) und ChatMessage.
Der Controller Layer bildet die Schnittstelle zwischen Frontend und
Backend-Logik. Die Routes definieren die API-Endpunkte, die Controller
verarbeiten die eingehenden Requests und reichen diese an die Services weiter.
Eine Auth Middleware prüft bei geschützten Routen den JWT-Token.
Eine Auth Middleware prüft bei geschützten Routen den X-User-Id Header.
\subsubsection{Service Layer}

102
package-lock.json generated
View File

@@ -72,7 +72,6 @@
"dotenv": "^16.4.7",
"express": "^5.2.1",
"ical.js": "^2.2.1",
"jsonwebtoken": "^9.0.3",
"mongoose": "^9.1.1",
"openai": "^6.15.0",
"pino": "^10.1.1",
@@ -85,7 +84,6 @@
"@types/express": "^5.0.6",
"@types/ical": "^0.8.3",
"@types/jest": "^30.0.0",
"@types/jsonwebtoken": "^9.0.10",
"@types/node": "^24.10.1",
"jest": "^30.2.0",
"pino-pretty": "^13.1.3",
@@ -4936,20 +4934,6 @@
"dev": true,
"license": "MIT"
},
"node_modules/@types/jsonwebtoken": {
"version": "9.0.10",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/ms": "*",
"@types/node": "*"
}
},
"node_modules/@types/ms": {
"version": "2.1.0",
"dev": true,
"license": "MIT"
},
"node_modules/@types/node": {
"version": "24.10.1",
"license": "MIT",
@@ -6076,10 +6060,6 @@
"ieee754": "^1.1.13"
}
},
"node_modules/buffer-equal-constant-time": {
"version": "1.0.1",
"license": "BSD-3-Clause"
},
"node_modules/buffer-from": {
"version": "1.1.2",
"license": "MIT"
@@ -6844,13 +6824,6 @@
"dev": true,
"license": "MIT"
},
"node_modules/ecdsa-sig-formatter": {
"version": "1.0.11",
"license": "Apache-2.0",
"dependencies": {
"safe-buffer": "^5.0.1"
}
},
"node_modules/ee-first": {
"version": "1.1.1",
"license": "MIT"
@@ -13280,36 +13253,6 @@
"node": ">=6"
}
},
"node_modules/jsonwebtoken": {
"version": "9.0.3",
"license": "MIT",
"dependencies": {
"jws": "^4.0.1",
"lodash.includes": "^4.3.0",
"lodash.isboolean": "^3.0.3",
"lodash.isinteger": "^4.0.4",
"lodash.isnumber": "^3.0.3",
"lodash.isplainobject": "^4.0.6",
"lodash.isstring": "^4.0.1",
"lodash.once": "^4.0.0",
"ms": "^2.1.1",
"semver": "^7.5.4"
},
"engines": {
"node": ">=12",
"npm": ">=6"
}
},
"node_modules/jsonwebtoken/node_modules/semver": {
"version": "7.7.3",
"license": "ISC",
"bin": {
"semver": "bin/semver.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/jsx-ast-utils": {
"version": "3.3.5",
"dev": true,
@@ -13324,23 +13267,6 @@
"node": ">=4.0"
}
},
"node_modules/jwa": {
"version": "2.0.1",
"license": "MIT",
"dependencies": {
"buffer-equal-constant-time": "^1.0.1",
"ecdsa-sig-formatter": "1.0.11",
"safe-buffer": "^5.0.1"
}
},
"node_modules/jws": {
"version": "4.0.1",
"license": "MIT",
"dependencies": {
"jwa": "^2.0.1",
"safe-buffer": "^5.0.1"
}
},
"node_modules/kareem": {
"version": "3.0.0",
"license": "Apache-2.0",
@@ -13502,30 +13428,6 @@
"version": "4.0.8",
"license": "MIT"
},
"node_modules/lodash.includes": {
"version": "4.3.0",
"license": "MIT"
},
"node_modules/lodash.isboolean": {
"version": "3.0.3",
"license": "MIT"
},
"node_modules/lodash.isinteger": {
"version": "4.0.4",
"license": "MIT"
},
"node_modules/lodash.isnumber": {
"version": "3.0.3",
"license": "MIT"
},
"node_modules/lodash.isplainobject": {
"version": "4.0.6",
"license": "MIT"
},
"node_modules/lodash.isstring": {
"version": "4.0.1",
"license": "MIT"
},
"node_modules/lodash.memoize": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
@@ -13538,10 +13440,6 @@
"dev": true,
"license": "MIT"
},
"node_modules/lodash.once": {
"version": "4.1.1",
"license": "MIT"
},
"node_modules/lodash.throttle": {
"version": "4.1.1",
"license": "MIT"