mirror of
https://github.com/naturalcrit/homebrewery.git
synced 2026-01-11 13:22:39 +00:00
Merge pull request #1282 from naturalcrit/ReduceRedundancyInServerJS
[WIP] Move common Server.js logic into functions
This commit is contained in:
5
package-lock.json
generated
5
package-lock.json
generated
@@ -3869,6 +3869,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"express-async-handler": {
|
||||||
|
"version": "1.1.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/express-async-handler/-/express-async-handler-1.1.4.tgz",
|
||||||
|
"integrity": "sha512-HdmbVF4V4w1q/iz++RV7bUxIeepTukWewiJGkoCKQMtvPF11MLTa7It9PRc/reysXXZSEyD4Pthchju+IUbMiQ=="
|
||||||
|
},
|
||||||
"express-static-gzip": {
|
"express-static-gzip": {
|
||||||
"version": "2.1.1",
|
"version": "2.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/express-static-gzip/-/express-static-gzip-2.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/express-static-gzip/-/express-static-gzip-2.1.1.tgz",
|
||||||
|
|||||||
@@ -49,17 +49,18 @@
|
|||||||
"cookie-parser": "^1.4.5",
|
"cookie-parser": "^1.4.5",
|
||||||
"create-react-class": "^15.7.0",
|
"create-react-class": "^15.7.0",
|
||||||
"express": "^4.17.1",
|
"express": "^4.17.1",
|
||||||
|
"express-async-handler": "^1.1.4",
|
||||||
"express-static-gzip": "2.1.1",
|
"express-static-gzip": "2.1.1",
|
||||||
"fs-extra": "9.1.0",
|
"fs-extra": "9.1.0",
|
||||||
"googleapis": "67.1.1",
|
"googleapis": "67.1.1",
|
||||||
"jwt-simple": "^0.5.6",
|
"jwt-simple": "^0.5.6",
|
||||||
"less": "^3.13.1",
|
"less": "^3.13.1",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
|
"marked": "2.0.1",
|
||||||
|
"markedLegacy": "npm:marked@^0.3.19",
|
||||||
"moment": "^2.29.1",
|
"moment": "^2.29.1",
|
||||||
"mongoose": "^5.12.0",
|
"mongoose": "^5.12.0",
|
||||||
"nanoid": "3.1.21",
|
"nanoid": "3.1.21",
|
||||||
"markedLegacy": "npm:marked@^0.3.19",
|
|
||||||
"marked": "2.0.1",
|
|
||||||
"nconf": "^0.11.2",
|
"nconf": "^0.11.2",
|
||||||
"prop-types": "15.7.2",
|
"prop-types": "15.7.2",
|
||||||
"query-string": "6.14.1",
|
"query-string": "6.14.1",
|
||||||
|
|||||||
232
server.js
232
server.js
@@ -8,6 +8,23 @@ const homebrewApi = require('./server/homebrew.api.js');
|
|||||||
const GoogleActions = require('./server/googleActions.js');
|
const GoogleActions = require('./server/googleActions.js');
|
||||||
const serveCompressedStaticAssets = require('./server/static-assets.mv.js');
|
const serveCompressedStaticAssets = require('./server/static-assets.mv.js');
|
||||||
const sanitizeFilename = require('sanitize-filename');
|
const sanitizeFilename = require('sanitize-filename');
|
||||||
|
const asyncHandler = require('express-async-handler');
|
||||||
|
|
||||||
|
//Get the brew object from the HB database or Google Drive
|
||||||
|
const getBrewFromId = asyncHandler(async (id, accessType)=>{
|
||||||
|
if(accessType !== 'edit' && accessType !== 'share')
|
||||||
|
throw ('Invalid Access Type when getting brew');
|
||||||
|
let brew;
|
||||||
|
if(id.length > 12) {
|
||||||
|
const googleId = id.slice(0, -12);
|
||||||
|
id = id.slice(-12);
|
||||||
|
brew = await GoogleActions.readFileMetadata(config.get('google_api_key'), googleId, id, accessType);
|
||||||
|
} else {
|
||||||
|
brew = await HomebrewModel.get(accessType == 'edit' ? { editId: id } : { shareId: id });
|
||||||
|
brew.sanatize(true);
|
||||||
|
}
|
||||||
|
return brew;
|
||||||
|
});
|
||||||
|
|
||||||
app.use('/', serveCompressedStaticAssets(`${__dirname}/build`));
|
app.use('/', serveCompressedStaticAssets(`${__dirname}/build`));
|
||||||
|
|
||||||
@@ -65,14 +82,10 @@ app.get('/robots.txt', (req, res)=>{
|
|||||||
return res.sendFile(`${__dirname}/robots.txt`);
|
return res.sendFile(`${__dirname}/robots.txt`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
//Source page
|
//Source page
|
||||||
app.get('/source/:id', (req, res)=>{
|
app.get('/source/:id', asyncHandler(async (req, res)=>{
|
||||||
if(req.params.id.length > 12) {
|
const brew = await getBrewFromId(req.params.id, 'share');
|
||||||
const googleId = req.params.id.slice(0, -12);
|
|
||||||
const shareId = req.params.id.slice(-12);
|
|
||||||
GoogleActions.readFileMetadata(config.get('google_api_key'), googleId, shareId, 'share')
|
|
||||||
.then((brew)=>{
|
|
||||||
const replaceStrings = { '&': '&', '<': '<', '>': '>' };
|
const replaceStrings = { '&': '&', '<': '<', '>': '>' };
|
||||||
let text = brew.text;
|
let text = brew.text;
|
||||||
for (const replaceStr in replaceStrings) {
|
for (const replaceStr in replaceStrings) {
|
||||||
@@ -80,38 +93,13 @@ app.get('/source/:id', (req, res)=>{
|
|||||||
}
|
}
|
||||||
text = `<code><pre style="white-space: pre-wrap;">${text}</pre></code>`;
|
text = `<code><pre style="white-space: pre-wrap;">${text}</pre></code>`;
|
||||||
res.status(200).send(text);
|
res.status(200).send(text);
|
||||||
})
|
}));
|
||||||
.catch((err)=>{
|
|
||||||
console.log(err);
|
|
||||||
return res.status(400).send('Can\'t get brew from Google');
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
HomebrewModel.get({ shareId: req.params.id })
|
|
||||||
.then((brew)=>{
|
|
||||||
const replaceStrings = { '&': '&', '<': '<', '>': '>' };
|
|
||||||
let text = brew.text;
|
|
||||||
for (const replaceStr in replaceStrings) {
|
|
||||||
text = text.replaceAll(replaceStr, replaceStrings[replaceStr]);
|
|
||||||
}
|
|
||||||
text = `<code><pre style="white-space: pre-wrap;">${text}</pre></code>`;
|
|
||||||
res.status(200).send(text);
|
|
||||||
})
|
|
||||||
.catch((err)=>{
|
|
||||||
console.log(err);
|
|
||||||
return res.status(404).send('Could not find Homebrew with that id');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
//Download brew source page
|
//Download brew source page
|
||||||
app.get('/download/:id', (req, res)=>{
|
app.get('/download/:id', asyncHandler(async (req, res)=>{
|
||||||
|
const brew = await getBrewFromId(req.params.id, 'share');
|
||||||
const prefix = 'HB - ';
|
const prefix = 'HB - ';
|
||||||
|
|
||||||
if(req.params.id.length > 12) {
|
|
||||||
const googleId = req.params.id.slice(0, -12);
|
|
||||||
const shareId = req.params.id.slice(-12);
|
|
||||||
GoogleActions.readFileMetadata(config.get('google_api_key'), googleId, shareId, 'share')
|
|
||||||
.then((brew)=>{
|
|
||||||
let fileName = sanitizeFilename(`${prefix}${brew.title}`).replaceAll(' ', '');
|
let fileName = sanitizeFilename(`${prefix}${brew.title}`).replaceAll(' ', '');
|
||||||
if(!fileName || !fileName.length) { fileName = `${prefix}-Untitled-Brew`; };
|
if(!fileName || !fileName.length) { fileName = `${prefix}-Untitled-Brew`; };
|
||||||
res.set({
|
res.set({
|
||||||
@@ -120,29 +108,7 @@ app.get('/download/:id', (req, res)=>{
|
|||||||
'Content-Disposition' : `attachment; filename="${fileName}.txt"`
|
'Content-Disposition' : `attachment; filename="${fileName}.txt"`
|
||||||
});
|
});
|
||||||
res.status(200).send(brew.text);
|
res.status(200).send(brew.text);
|
||||||
})
|
}));
|
||||||
.catch((err)=>{
|
|
||||||
console.log(err);
|
|
||||||
return res.status(400).send('Can\'t get brew from Google');
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
HomebrewModel.get({ shareId: req.params.id })
|
|
||||||
.then((brew)=>{
|
|
||||||
let fileName = sanitizeFilename(`${prefix}${brew.title}`).replaceAll(' ', '');
|
|
||||||
if(!fileName || !fileName.length) { fileName = `${prefix}-Untitled-Brew`; };
|
|
||||||
res.set({
|
|
||||||
'Cache-Control' : 'no-cache',
|
|
||||||
'Content-Type' : 'text/plain',
|
|
||||||
'Content-Disposition' : `attachment; filename="${fileName}.txt"`
|
|
||||||
});
|
|
||||||
res.status(200).send(brew.text);
|
|
||||||
})
|
|
||||||
.catch((err)=>{
|
|
||||||
console.log(err);
|
|
||||||
return res.status(404).send('Could not find Homebrew with that id');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
//User Page
|
//User Page
|
||||||
app.get('/user/:username', async (req, res, next)=>{
|
app.get('/user/:username', async (req, res, next)=>{
|
||||||
@@ -170,123 +136,45 @@ app.get('/user/:username', async (req, res, next)=>{
|
|||||||
});
|
});
|
||||||
|
|
||||||
//Edit Page
|
//Edit Page
|
||||||
app.get('/edit/:id', (req, res, next)=>{
|
app.get('/edit/:id', asyncHandler(async (req, res, next)=>{
|
||||||
res.header('Cache-Control', 'no-cache, no-store'); //reload the latest saved brew when pressing back button, not the cached version before save.
|
res.header('Cache-Control', 'no-cache, no-store'); //reload the latest saved brew when pressing back button, not the cached version before save.
|
||||||
if(req.params.id.length > 12) {
|
const brew = await getBrewFromId(req.params.id, 'edit');
|
||||||
const googleId = req.params.id.slice(0, -12);
|
|
||||||
const editId = req.params.id.slice(-12);
|
|
||||||
GoogleActions.readFileMetadata(config.get('google_api_key'), googleId, editId, 'edit')
|
|
||||||
.then((brew)=>{
|
|
||||||
req.brew = brew; //TODO Need to sanitize later
|
|
||||||
return next();
|
|
||||||
})
|
|
||||||
.catch((err)=>{
|
|
||||||
console.log(err);
|
|
||||||
return res.status(400).send('Can\'t get brew from Google');
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
HomebrewModel.get({ editId: req.params.id })
|
|
||||||
.then((brew)=>{
|
|
||||||
req.brew = brew.sanatize();
|
|
||||||
return next();
|
|
||||||
})
|
|
||||||
.catch((err)=>{
|
|
||||||
console.log(err);
|
|
||||||
return res.status(400).send(`Can't get that`);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
//New Page
|
|
||||||
app.get('/new/:id', (req, res, next)=>{
|
|
||||||
if(req.params.id.length > 12) {
|
|
||||||
const googleId = req.params.id.slice(0, -12);
|
|
||||||
const shareId = req.params.id.slice(-12);
|
|
||||||
GoogleActions.readFileMetadata(config.get('google_api_key'), googleId, shareId, 'share')
|
|
||||||
.then((brew)=>{
|
|
||||||
req.brew = brew; //TODO Need to sanitize later
|
|
||||||
return next();
|
|
||||||
})
|
|
||||||
.catch((err)=>{
|
|
||||||
console.log(err);
|
|
||||||
return res.status(400).send('Can\'t get brew from Google');
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
HomebrewModel.get({ shareId: req.params.id })
|
|
||||||
.then((brew)=>{
|
|
||||||
req.brew = brew;
|
req.brew = brew;
|
||||||
return next();
|
return next();
|
||||||
})
|
}));
|
||||||
.catch((err)=>{
|
|
||||||
console.log(err);
|
//New Page
|
||||||
return res.status(400).send(`Can't get that`);
|
app.get('/new/:id', asyncHandler(async (req, res, next)=>{
|
||||||
});
|
const brew = await getBrewFromId(req.params.id, 'share');
|
||||||
}
|
req.brew = brew;
|
||||||
});
|
return next();
|
||||||
|
}));
|
||||||
|
|
||||||
//Share Page
|
//Share Page
|
||||||
app.get('/share/:id', (req, res, next)=>{
|
app.get('/share/:id', asyncHandler(async (req, res, next)=>{
|
||||||
|
const brew = await getBrewFromId(req.params.id, 'share');
|
||||||
|
|
||||||
if(req.params.id.length > 12) {
|
if(req.params.id.length > 12) {
|
||||||
const googleId = req.params.id.slice(0, -12);
|
const googleId = req.params.id.slice(0, -12);
|
||||||
const shareId = req.params.id.slice(-12);
|
const shareId = req.params.id.slice(-12);
|
||||||
GoogleActions.readFileMetadata(config.get('google_api_key'), googleId, shareId, 'share')
|
await GoogleActions.increaseView(googleId, shareId, 'share', brew)
|
||||||
.then((brew)=>{
|
.catch((err)=>{next(err);});
|
||||||
GoogleActions.increaseView(googleId, shareId, 'share', brew);
|
|
||||||
return brew;
|
|
||||||
})
|
|
||||||
.then((brew)=>{
|
|
||||||
req.brew = brew; //TODO Need to sanitize later
|
|
||||||
return next();
|
|
||||||
})
|
|
||||||
.catch((err)=>{
|
|
||||||
console.log(err);
|
|
||||||
return res.status(400).send('Can\'t get brew from Google');
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
HomebrewModel.get({ shareId: req.params.id })
|
await brew.increaseView();
|
||||||
.then((brew)=>{
|
|
||||||
return brew.increaseView();
|
|
||||||
})
|
|
||||||
.then((brew)=>{
|
|
||||||
req.brew = brew.sanatize(true);
|
|
||||||
return next();
|
|
||||||
})
|
|
||||||
.catch((err)=>{
|
|
||||||
console.log(err);
|
|
||||||
return res.status(400).send(`Can't get that`);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
req.brew = brew;
|
||||||
|
return next();
|
||||||
|
}));
|
||||||
|
|
||||||
//Print Page
|
//Print Page
|
||||||
app.get('/print/:id', (req, res, next)=>{
|
app.get('/print/:id', asyncHandler(async (req, res, next)=>{
|
||||||
if(req.params.id.length > 12) {
|
const brew = await getBrewFromId(req.params.id, 'share');
|
||||||
const googleId = req.params.id.slice(0, -12);
|
req.brew = brew;
|
||||||
const shareId = req.params.id.slice(-12);
|
|
||||||
GoogleActions.readFileMetadata(config.get('google_api_key'), googleId, shareId, 'share')
|
|
||||||
.then((brew)=>{
|
|
||||||
req.brew = brew; //TODO Need to sanitize later
|
|
||||||
return next();
|
return next();
|
||||||
})
|
}));
|
||||||
.catch((err)=>{
|
|
||||||
console.log(err);
|
|
||||||
return res.status(400).send('Can\'t get brew from Google');
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
HomebrewModel.get({ shareId: req.params.id })
|
|
||||||
.then((brew)=>{
|
|
||||||
req.brew = brew.sanatize(true);
|
|
||||||
return next();
|
|
||||||
})
|
|
||||||
.catch((err)=>{
|
|
||||||
console.log(err);
|
|
||||||
return res.status(400).send(`Can't get that`);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
//Render the page
|
//Render the page
|
||||||
//const render = require('.build/render');
|
|
||||||
const templateFn = require('./client/template.js');
|
const templateFn = require('./client/template.js');
|
||||||
app.use((req, res)=>{
|
app.use((req, res)=>{
|
||||||
const props = {
|
const props = {
|
||||||
@@ -303,11 +191,35 @@ app.use((req, res)=>{
|
|||||||
templateFn('homebrew', title = req.brew ? req.brew.title : '', props)
|
templateFn('homebrew', title = req.brew ? req.brew.title : '', props)
|
||||||
.then((page)=>{ res.send(page); })
|
.then((page)=>{ res.send(page); })
|
||||||
.catch((err)=>{
|
.catch((err)=>{
|
||||||
|
console.log('TEMPLATE ERROR');
|
||||||
console.log(err);
|
console.log(err);
|
||||||
return res.sendStatus(500);
|
return res.sendStatus(500);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//v=====----- Error-Handling Middleware -----=====v//
|
||||||
|
//Format Errors so all fields will be sent
|
||||||
|
const replaceErrors = (key, value)=>{
|
||||||
|
if(value instanceof Error) {
|
||||||
|
const error = {};
|
||||||
|
Object.getOwnPropertyNames(value).forEach(function (key) {
|
||||||
|
error[key] = value[key];
|
||||||
|
});
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getPureError = (error)=>{
|
||||||
|
return JSON.parse(JSON.stringify(error, replaceErrors));
|
||||||
|
};
|
||||||
|
|
||||||
|
app.use((err, req, res, next)=>{
|
||||||
|
const status = err.status || 500;
|
||||||
|
console.error(err);
|
||||||
|
res.status(status).send(getPureError(err));
|
||||||
|
});
|
||||||
|
//^=====--------------------------------------=====^//
|
||||||
|
|
||||||
const PORT = process.env.PORT || config.get('web_port') || 8000;
|
const PORT = process.env.PORT || config.get('web_port') || 8000;
|
||||||
app.listen(PORT);
|
app.listen(PORT);
|
||||||
|
|||||||
@@ -240,6 +240,7 @@ GoogleActions = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
readFileMetadata : async (auth, id, accessId, accessType)=>{
|
readFileMetadata : async (auth, id, accessId, accessType)=>{
|
||||||
|
|
||||||
const drive = google.drive({ version: 'v3', auth: auth });
|
const drive = google.drive({ version: 'v3', auth: auth });
|
||||||
|
|
||||||
const obj = await drive.files.get({
|
const obj = await drive.files.get({
|
||||||
@@ -248,7 +249,7 @@ GoogleActions = {
|
|||||||
})
|
})
|
||||||
.catch((err)=>{
|
.catch((err)=>{
|
||||||
console.log('Error loading from Google');
|
console.log('Error loading from Google');
|
||||||
console.error(err);
|
throw (err);
|
||||||
return;
|
return;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -345,7 +346,10 @@ GoogleActions = {
|
|||||||
increaseView : async (id, accessId, accessType, brew)=>{
|
increaseView : async (id, accessId, accessType, brew)=>{
|
||||||
//service account because this is modifying another user's file properties
|
//service account because this is modifying another user's file properties
|
||||||
//so we need extended scope
|
//so we need extended scope
|
||||||
const keys = JSON.parse(config.get('service_account'));
|
const keys = typeof(config.get('service_account')) == 'string' ?
|
||||||
|
JSON.parse(config.get('service_account')) :
|
||||||
|
config.get('service_account');
|
||||||
|
|
||||||
const auth = google.auth.fromJSON(keys);
|
const auth = google.auth.fromJSON(keys);
|
||||||
auth.scopes = ['https://www.googleapis.com/auth/drive'];
|
auth.scopes = ['https://www.googleapis.com/auth/drive'];
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user