feat: Add OIDC authentication with Authentik integration

- Add OIDC login flow with Authentik provider
- Implement session-based auth with Redis store
- Add avatar display from OIDC claims
- Fix input field performance with react-textarea-autosize
- Stabilize callbacks to prevent unnecessary re-renders
- Fix history loading to skip empty session files
- Add 2-row default height for input textarea

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2025-12-18 06:07:22 +01:00
parent cfee1711dc
commit 1186cb1b5e
23 changed files with 2884 additions and 87 deletions

View File

@@ -1,7 +1,12 @@
import { useState, useRef, useCallback, useEffect } from 'react';
const WS_URL = import.meta.env.VITE_WS_URL || 'ws://100.105.142.13:3001';
const API_URL = import.meta.env.VITE_API_URL || 'http://100.105.142.13:3001';
// Build WebSocket URL from current location
function getWsUrl() {
if (import.meta.env.VITE_WS_URL) return import.meta.env.VITE_WS_URL;
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
return `${protocol}//${window.location.host}/ws`;
}
const MAX_FILE_SIZE = 10 * 1024 * 1024; // 10MB
export function useClaudeSession() {
@@ -49,7 +54,7 @@ export function useClaudeSession() {
const connect = useCallback(() => {
if (wsRef.current?.readyState === WebSocket.OPEN) return;
const ws = new WebSocket(WS_URL);
const ws = new WebSocket(getWsUrl());
wsRef.current = ws;
ws.onopen = () => {
@@ -350,7 +355,9 @@ export function useClaudeSession() {
try {
const encodedProject = encodeURIComponent(project);
const hostParam = host ? `?host=${host}` : '';
const response = await fetch(`${API_URL}/api/history/${encodedProject}${hostParam}`);
const response = await fetch(`/api/history/${encodedProject}${hostParam}`, {
credentials: 'include',
});
if (response.ok) {
const data = await response.json();
if (data.messages && data.messages.length > 0) {
@@ -397,9 +404,10 @@ export function useClaudeSession() {
}
try {
const response = await fetch(`${API_URL}/api/upload/${sessionId}`, {
const response = await fetch(`/api/upload/${sessionId}`, {
method: 'POST',
body: formData
body: formData,
credentials: 'include',
});
if (!response.ok) {