0
0
mirror of https://github.com/naturalcrit/homebrewery.git synced 2026-01-01 15:12:40 +00:00

Merge pull request #4448 from G-Ambatte/addDBCheckMiddleware

Add DB check middleware
This commit is contained in:
Trevor Buckner
2025-10-06 14:20:28 -04:00
committed by GitHub
7 changed files with 77 additions and 5 deletions

View File

@@ -112,6 +112,15 @@ const ErrorNavItem = ({ error = '', clearError })=>{
</Nav.item>; </Nav.item>;
} }
if(HBErrorCode === '13') {
return <Nav.item className='save error' icon='fas fa-exclamation-triangle'>
Oops!
<div className='errorContainer' onClick={clearError}>
Server has lost connection to the database.
</div>
</Nav.item>;
}
if(errorCode === 'ECONNABORTED') { if(errorCode === 'ECONNABORTED') {
return <Nav.item className='save error' icon='fas fa-exclamation-triangle'> return <Nav.item className='save error' icon='fas fa-exclamation-triangle'>
Oops! Oops!

View File

@@ -196,6 +196,12 @@ const errorIndex = (props)=>{
**Brew ID:** ${props.brew.brewId}`, **Brew ID:** ${props.brew.brewId}`,
// Database Connection Lost
'13' : dedent`
## Database connection has been lost.
The server could not communicate with the database.`,
//account page when account is not defined //account page when account is not defined
'50' : dedent` '50' : dedent`
## You are not signed in ## You are not signed in

View File

@@ -35,6 +35,7 @@ import contentNegotiation from './middleware/content-negotiation.js';
import bodyParser from 'body-parser'; import bodyParser from 'body-parser';
import cookieParser from 'cookie-parser'; import cookieParser from 'cookie-parser';
import forceSSL from './forcessl.mw.js'; import forceSSL from './forcessl.mw.js';
import dbCheck from './middleware/dbCheck.js';
const sanitizeBrew = (brew, accessType)=>{ const sanitizeBrew = (brew, accessType)=>{
@@ -274,7 +275,7 @@ app.get('/metadata/:id', asyncHandler(getBrew('share')), (req, res)=>{
app.get('/css/:id', asyncHandler(getBrew('share')), (req, res)=>{getCSS(req, res);}); app.get('/css/:id', asyncHandler(getBrew('share')), (req, res)=>{getCSS(req, res);});
//User Page //User Page
app.get('/user/:username', async (req, res, next)=>{ app.get('/user/:username', dbCheck, async (req, res, next)=>{
const ownAccount = req.account && (req.account.username == req.params.username); const ownAccount = req.account && (req.account.username == req.params.username);
req.ogMeta = { ...defaultMetaTags, req.ogMeta = { ...defaultMetaTags,
@@ -346,7 +347,7 @@ app.get('/user/:username', async (req, res, next)=>{
}); });
//Change author name on brews //Change author name on brews
app.put('/api/user/rename', async (req, res)=>{ app.put('/api/user/rename', dbCheck, async (req, res)=>{
const { username, newUsername } = req.body; const { username, newUsername } = req.body;
const ownAccount = req.account && (req.account.username == newUsername); const ownAccount = req.account && (req.account.username == newUsername);
@@ -432,7 +433,7 @@ app.get('/new', asyncHandler(async(req, res, next)=>{
})); }));
//Share Page //Share Page
app.get('/share/:id', asyncHandler(getBrew('share')), asyncHandler(async (req, res, next)=>{ app.get('/share/:id', dbCheck, asyncHandler(getBrew('share')), asyncHandler(async (req, res, next)=>{
const { brew } = req; const { brew } = req;
req.ogMeta = { ...defaultMetaTags, req.ogMeta = { ...defaultMetaTags,
title : `${req.brew.title || 'Untitled Brew'} - ${req.brew.authors[0] || 'No author.'}`, title : `${req.brew.title || 'Untitled Brew'} - ${req.brew.authors[0] || 'No author.'}`,
@@ -459,7 +460,7 @@ app.get('/share/:id', asyncHandler(getBrew('share')), asyncHandler(async (req, r
})); }));
//Account Page //Account Page
app.get('/account', asyncHandler(async (req, res, next)=>{ app.get('/account', dbCheck, asyncHandler(async (req, res, next)=>{
const data = {}; const data = {};
data.title = 'Account Information Page'; data.title = 'Account Information Page';

View File

@@ -22,6 +22,14 @@ const handleConnectionError = (error)=>{
} }
}; };
const addListeners = (conn)=>{
conn.connection.on('disconnecting', ()=>{console.log('Mongo disconnecting...');});
conn.connection.on('disconnected', ()=>{console.log('Mongo disconnected!');});
conn.connection.on('connecting', ()=>{console.log('Mongo connecting...');});
conn.connection.on('connected', ()=>{console.log('Mongo connected!');});
return conn;
};
const disconnect = async ()=>{ const disconnect = async ()=>{
return await Mongoose.disconnect(); return await Mongoose.disconnect();
}; };
@@ -31,10 +39,12 @@ const connect = async (config)=>{
retryWrites : false, retryWrites : false,
autoIndex : (config.get('local_environments').includes(config.get('node_env'))) autoIndex : (config.get('local_environments').includes(config.get('node_env')))
}) })
.catch((error)=>handleConnectionError(error)); .then(addListeners(Mongoose))
.catch((error)=>handleConnectionError(error));
}; };
export default { export default {
connect, connect,
disconnect disconnect
}; };

View File

@@ -13,6 +13,7 @@ import { md5 } from 'hash-wasm';
import { splitTextStyleAndMetadata, import { splitTextStyleAndMetadata,
brewSnippetsToJSON, debugTextMismatch } from '../shared/helpers.js'; brewSnippetsToJSON, debugTextMismatch } from '../shared/helpers.js';
import checkClientVersion from './middleware/check-client-version.js'; import checkClientVersion from './middleware/check-client-version.js';
import dbCheck from './middleware/dbCheck.js';
const router = express.Router(); const router = express.Router();
@@ -530,6 +531,8 @@ const api = {
} }
}; };
router.use(dbCheck);
router.post('/api', checkClientVersion, asyncHandler(api.newBrew)); router.post('/api', checkClientVersion, asyncHandler(api.newBrew));
router.put('/api/:id', checkClientVersion, asyncHandler(api.getBrew('edit', false)), asyncHandler(api.updateBrew)); router.put('/api/:id', checkClientVersion, asyncHandler(api.getBrew('edit', false)), asyncHandler(api.updateBrew));
router.put('/api/update/:id', checkClientVersion, asyncHandler(api.getBrew('edit', false)), asyncHandler(api.updateBrew)); router.put('/api/update/:id', checkClientVersion, asyncHandler(api.getBrew('edit', false)), asyncHandler(api.updateBrew));

View File

@@ -0,0 +1,15 @@
import mongoose from 'mongoose';
import config from '../config.js';
export default (req, res, next)=>{
// Bypass DB checks during testing
if(config.get('node_env') == 'test') return next();
if(mongoose.connection.readyState == 1) return next();
throw {
HBErrorCode : '13',
name : 'Database Connection Error',
message : 'Unable to connect to database',
status : mongoose.connection.readyState
};
};

View File

@@ -0,0 +1,28 @@
import mongoose from 'mongoose';
import dbCheck from './dbCheck.js';
import config from '../config.js';
describe('dbCheck middleware', ()=>{
const next = jest.fn();
afterEach(()=>jest.clearAllMocks());
it('should skip check in test mode', ()=>{
config.get = jest.fn(()=>'test');
expect(()=>dbCheck({}, {}, next)).not.toThrow();
expect(next).toHaveBeenCalled();
});
it('should call next if readyState == 1', ()=>{
config.get = jest.fn(()=>'production');
mongoose.connection.readyState = 1;
dbCheck({}, {}, next);
expect(next).toHaveBeenCalled();
});
it('should throw if readyState != 1', ()=>{
config.get = jest.fn(()=>'production');
mongoose.connection.readyState = 99;
expect(()=>dbCheck({}, {}, next)).toThrow(/Unable to connect/);
});
});