- 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>
89 lines
2.9 KiB
JavaScript
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;
|