Merge branch 'main' into feat/math-rendering

This commit is contained in:
viper151
2025-11-05 23:02:01 +01:00
committed by GitHub
6 changed files with 84 additions and 10 deletions

View File

@@ -35,6 +35,7 @@ VITE_PORT=5173
# DATABASE_PATH=/path/to/your/custom/auth.db
#
# Claude Code context window size (maximum tokens per session)
# Note: VITE_ prefix makes it available to frontend
VITE_CONTEXT_WINDOW=160000
CONTEXT_WINDOW=160000
# VITE_IS_PLATFORM=false

View File

@@ -117,6 +117,15 @@ const userDb = {
} catch (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;
}
}
};

View File

@@ -170,6 +170,19 @@ const wss = new WebSocketServer({
verifyClient: (info) => {
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
const url = new URL(info.req.url, 'http://localhost');
const token = url.searchParams.get('token') ||
@@ -196,6 +209,14 @@ app.use(cors());
app.use(express.json({ limit: '50mb' }));
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)
app.use('/api', validateApiKey);

View File

@@ -20,6 +20,22 @@ const validateApiKey = (req, res, next) => {
// JWT authentication middleware
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 token = authHeader && authHeader.split(' ')[1]; // Bearer TOKEN
@@ -29,13 +45,13 @@ const authenticateToken = async (req, res, next) => {
try {
const decoded = jwt.verify(token, JWT_SECRET);
// Verify user still exists and is active
const user = userDb.getUserById(decoded.userId);
if (!user) {
return res.status(401).json({ error: 'Invalid token. User not found.' });
}
req.user = user;
next();
} catch (error) {
@@ -58,10 +74,25 @@ const generateToken = (user) => {
// WebSocket authentication function
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) {
return null;
}
try {
const decoded = jwt.verify(token, JWT_SECRET);
return decoded;

View File

@@ -26,6 +26,12 @@ const LoadingScreen = () => (
const ProtectedRoute = ({ children }) => {
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) {
return <LoadingScreen />;
}

View File

@@ -29,31 +29,38 @@ export const AuthProvider = ({ children }) => {
// Check authentication status on mount
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();
}, []);
const checkAuthStatus = async () => {
try {
console.log('[AuthContext] Checking auth status...');
setIsLoading(true);
setError(null);
// Check if system needs setup
const statusResponse = await api.auth.status();
const statusData = await statusResponse.json();
console.log('[AuthContext] Status response:', statusData);
if (statusData.needsSetup) {
setNeedsSetup(true);
setIsLoading(false);
return;
}
// If we have a token, verify it
if (token) {
try {
const userResponse = await api.auth.user();
if (userResponse.ok) {
const userData = await userResponse.json();
setUser(userData.user);
@@ -75,7 +82,6 @@ export const AuthProvider = ({ children }) => {
console.error('[AuthContext] Auth status check failed:', error);
setError('Failed to check authentication status');
} finally {
console.log('[AuthContext] Auth check complete, isLoading=false');
setIsLoading(false);
}
};