mirror of
https://github.com/siteboon/claudecodeui.git
synced 2025-12-10 14:59:46 +00:00
Merge branch 'main' into feat/math-rendering
This commit is contained in:
@@ -35,6 +35,7 @@ VITE_PORT=5173
|
|||||||
# DATABASE_PATH=/path/to/your/custom/auth.db
|
# DATABASE_PATH=/path/to/your/custom/auth.db
|
||||||
#
|
#
|
||||||
# Claude Code context window size (maximum tokens per session)
|
# Claude Code context window size (maximum tokens per session)
|
||||||
# Note: VITE_ prefix makes it available to frontend
|
|
||||||
VITE_CONTEXT_WINDOW=160000
|
VITE_CONTEXT_WINDOW=160000
|
||||||
CONTEXT_WINDOW=160000
|
CONTEXT_WINDOW=160000
|
||||||
|
|
||||||
|
# VITE_IS_PLATFORM=false
|
||||||
|
|||||||
@@ -117,6 +117,15 @@ const userDb = {
|
|||||||
} catch (err) {
|
} catch (err) {
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
getFirstUser: () => {
|
||||||
|
try {
|
||||||
|
const row = db.prepare('SELECT id, username, created_at, last_login FROM users WHERE is_active = 1 LIMIT 1').get();
|
||||||
|
return row;
|
||||||
|
} catch (err) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -170,6 +170,19 @@ const wss = new WebSocketServer({
|
|||||||
verifyClient: (info) => {
|
verifyClient: (info) => {
|
||||||
console.log('WebSocket connection attempt to:', info.req.url);
|
console.log('WebSocket connection attempt to:', info.req.url);
|
||||||
|
|
||||||
|
// Platform mode: always allow connection
|
||||||
|
if (process.env.VITE_IS_PLATFORM === 'true') {
|
||||||
|
const user = authenticateWebSocket(null); // Will return first user
|
||||||
|
if (!user) {
|
||||||
|
console.log('[WARN] Platform mode: No user found in database');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
info.req.user = user;
|
||||||
|
console.log('[OK] Platform mode WebSocket authenticated for user:', user.username);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Normal mode: verify token
|
||||||
// Extract token from query parameters or headers
|
// Extract token from query parameters or headers
|
||||||
const url = new URL(info.req.url, 'http://localhost');
|
const url = new URL(info.req.url, 'http://localhost');
|
||||||
const token = url.searchParams.get('token') ||
|
const token = url.searchParams.get('token') ||
|
||||||
@@ -196,6 +209,14 @@ app.use(cors());
|
|||||||
app.use(express.json({ limit: '50mb' }));
|
app.use(express.json({ limit: '50mb' }));
|
||||||
app.use(express.urlencoded({ limit: '50mb', extended: true }));
|
app.use(express.urlencoded({ limit: '50mb', extended: true }));
|
||||||
|
|
||||||
|
// Public health check endpoint (no authentication required)
|
||||||
|
app.get('/health', (req, res) => {
|
||||||
|
res.json({
|
||||||
|
status: 'ok',
|
||||||
|
timestamp: new Date().toISOString()
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
// Optional API key validation (if configured)
|
// Optional API key validation (if configured)
|
||||||
app.use('/api', validateApiKey);
|
app.use('/api', validateApiKey);
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,22 @@ const validateApiKey = (req, res, next) => {
|
|||||||
|
|
||||||
// JWT authentication middleware
|
// JWT authentication middleware
|
||||||
const authenticateToken = async (req, res, next) => {
|
const authenticateToken = async (req, res, next) => {
|
||||||
|
// Platform mode: use single database user
|
||||||
|
if (process.env.VITE_IS_PLATFORM === 'true') {
|
||||||
|
try {
|
||||||
|
const user = userDb.getFirstUser();
|
||||||
|
if (!user) {
|
||||||
|
return res.status(500).json({ error: 'Platform mode: No user found in database' });
|
||||||
|
}
|
||||||
|
req.user = user;
|
||||||
|
return next();
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Platform mode error:', error);
|
||||||
|
return res.status(500).json({ error: 'Platform mode: Failed to fetch user' });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Normal OSS JWT validation
|
||||||
const authHeader = req.headers['authorization'];
|
const authHeader = req.headers['authorization'];
|
||||||
const token = authHeader && authHeader.split(' ')[1]; // Bearer TOKEN
|
const token = authHeader && authHeader.split(' ')[1]; // Bearer TOKEN
|
||||||
|
|
||||||
@@ -58,6 +74,21 @@ const generateToken = (user) => {
|
|||||||
|
|
||||||
// WebSocket authentication function
|
// WebSocket authentication function
|
||||||
const authenticateWebSocket = (token) => {
|
const authenticateWebSocket = (token) => {
|
||||||
|
// Platform mode: bypass token validation, return first user
|
||||||
|
if (process.env.VITE_IS_PLATFORM === 'true') {
|
||||||
|
try {
|
||||||
|
const user = userDb.getFirstUser();
|
||||||
|
if (user) {
|
||||||
|
return { userId: user.id, username: user.username };
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Platform mode WebSocket error:', error);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Normal OSS JWT validation
|
||||||
if (!token) {
|
if (!token) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,12 @@ const LoadingScreen = () => (
|
|||||||
const ProtectedRoute = ({ children }) => {
|
const ProtectedRoute = ({ children }) => {
|
||||||
const { user, isLoading, needsSetup } = useAuth();
|
const { user, isLoading, needsSetup } = useAuth();
|
||||||
|
|
||||||
|
// Platform mode: skip all auth UI and directly render children
|
||||||
|
if (import.meta.env.VITE_IS_PLATFORM === 'true') {
|
||||||
|
return children;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Normal OSS mode: standard auth flow
|
||||||
if (isLoading) {
|
if (isLoading) {
|
||||||
return <LoadingScreen />;
|
return <LoadingScreen />;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,19 +29,26 @@ export const AuthProvider = ({ children }) => {
|
|||||||
|
|
||||||
// Check authentication status on mount
|
// Check authentication status on mount
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
// Platform mode: skip all auth checks, set dummy user
|
||||||
|
if (import.meta.env.VITE_IS_PLATFORM === 'true') {
|
||||||
|
setUser({ username: 'platform-user' });
|
||||||
|
setNeedsSetup(false);
|
||||||
|
setIsLoading(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Normal OSS mode: check auth status
|
||||||
checkAuthStatus();
|
checkAuthStatus();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const checkAuthStatus = async () => {
|
const checkAuthStatus = async () => {
|
||||||
try {
|
try {
|
||||||
console.log('[AuthContext] Checking auth status...');
|
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
setError(null);
|
setError(null);
|
||||||
|
|
||||||
// Check if system needs setup
|
// Check if system needs setup
|
||||||
const statusResponse = await api.auth.status();
|
const statusResponse = await api.auth.status();
|
||||||
const statusData = await statusResponse.json();
|
const statusData = await statusResponse.json();
|
||||||
console.log('[AuthContext] Status response:', statusData);
|
|
||||||
|
|
||||||
if (statusData.needsSetup) {
|
if (statusData.needsSetup) {
|
||||||
setNeedsSetup(true);
|
setNeedsSetup(true);
|
||||||
@@ -75,7 +82,6 @@ export const AuthProvider = ({ children }) => {
|
|||||||
console.error('[AuthContext] Auth status check failed:', error);
|
console.error('[AuthContext] Auth status check failed:', error);
|
||||||
setError('Failed to check authentication status');
|
setError('Failed to check authentication status');
|
||||||
} finally {
|
} finally {
|
||||||
console.log('[AuthContext] Auth check complete, isLoading=false');
|
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user