immersive2/server/middleware/dbAuth.js
Michael Mainguy a772372b2b Add public URL sharing with express-pouchdb sync
- Add express-pouchdb for self-hosted PouchDB sync server
- Public databases (/db/public/:db) accessible without auth
- Add auth middleware for public/private database access
- Simplify share button to copy current URL to clipboard
- Move feature config from static JSON to dynamic API endpoint
- Add PouchDB sync to PouchData class for real-time collaboration
- Fix Express 5 compatibility by patching req.query
- Skip express.json() for /pouchdb routes (stream handling)
- Remove unused PouchdbPersistenceManager and old share system

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 11:49:56 -06:00

79 lines
2.4 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)
* /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();
}
// 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;