immersive2/server/middleware/dbAuth.js
Michael Mainguy 1e174e81d3
Some checks failed
Node.js CI / build (push) Waiting to run
Build / build (push) Failing after 15m8s
Add local database mode for browser-only diagrams
- Add /db/local/:db path type that stores diagrams locally without syncing
- New diagrams now default to local storage (browser-only)
- Share button creates public copy when sharing local diagrams
- Add storage type badges (Local/Public/Private) in diagram manager
- Add GitHub Actions workflow for automated builds
- Block local- database requests at server with 404

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 18:13:43 -06:00

89 lines
2.9 KiB
JavaScript

/**
* Database authentication middleware.
* Allows public databases to be accessed without auth.
* Private databases require authentication.
*/
/**
* Middleware to handle database authentication based on path.
*
* Database naming patterns:
* / - Root endpoint, always allowed (server info)
* /local-{dbname} - Should never reach server (client-only), return 404
* /public-{dbname} - No auth required, anyone can read/write
* /private-{dbname} - Auth required
* /{dbname} - Treated as private by default
*/
export function dbAuthMiddleware(req, res, next) {
// Extract the database name (first segment after /pouchdb/)
const pathParts = req.path.split('/').filter(Boolean);
const dbName = pathParts[0] || '';
// Allow root endpoint (server info check)
if (req.path === '/' || req.path === '') {
console.log(`[DB Auth] Root access: ${req.method} ${req.path}`);
return next();
}
// Local databases should never reach the server (they're browser-only)
if (dbName.startsWith('local-')) {
console.log(`[DB Auth] Local database access rejected: ${req.method} ${req.path}`);
return res.status(404).json({
error: 'not_found',
reason: 'Local databases are browser-only and do not sync to server'
});
}
// Check if this is a public database (name starts with 'public-')
const isPublic = dbName.startsWith('public-');
if (isPublic) {
// No auth required for public databases
console.log(`[DB Auth] Public access: ${req.method} ${req.path}`);
return next();
}
// For private databases, check for auth header
const auth = req.headers.authorization;
if (!auth) {
console.log(`[DB Auth] Unauthorized access attempt: ${req.method} ${req.path}`);
return res.status(401).json({
error: 'unauthorized',
reason: 'Authentication required for private databases'
});
}
// Parse Basic auth header
if (auth.startsWith('Basic ')) {
try {
const credentials = Buffer.from(auth.slice(6), 'base64').toString();
const [username, password] = credentials.split(':');
// For now, accept any credentials for private databases
// TODO: Implement proper user verification
req.dbUser = { name: username };
console.log(`[DB Auth] Authenticated: ${username} accessing ${req.path}`);
return next();
} catch (err) {
console.log(`[DB Auth] Invalid auth header: ${err.message}`);
}
}
// TODO: Add JWT/Bearer token support for Auth0 integration
if (auth.startsWith('Bearer ')) {
// For now, accept bearer tokens without verification
// TODO: Verify JWT with Auth0
req.dbUser = { name: 'bearer-user' };
console.log(`[DB Auth] Bearer token access: ${req.path}`);
return next();
}
return res.status(401).json({
error: 'unauthorized',
reason: 'Invalid authentication'
});
}
export default dbAuthMiddleware;