diff --git a/server/app.js b/server/app.js index 46984c458..385068561 100644 --- a/server/app.js +++ b/server/app.js @@ -15,8 +15,7 @@ const serveCompressedStaticAssets = require('./static-assets.mv.js'); const sanitizeFilename = require('sanitize-filename'); const asyncHandler = require('express-async-handler'); -const splitTextStyleAndMetadata = (req, res, next)=>{ - const { brew } = req; +const splitTextStyleAndMetadata = (brew)=>{ brew.text = brew.text.replaceAll('\r\n', '\n'); if(brew.text.startsWith('```metadata')) { const index = brew.text.indexOf('```\n\n'); @@ -30,26 +29,17 @@ const splitTextStyleAndMetadata = (req, res, next)=>{ brew.style = brew.text.slice(7, index - 1); brew.text = brew.text.slice(index + 5); } - req.brew = brew; - return next(); }; -const sanitizeBrew = (brew, full = false)=>{ - delete brew._id; - delete brew.__v; - if(full){ - delete brew.editId; +const sanitizeBrew = (brew, accessType)=>{ + brew._id = undefined; + brew.__v = undefined; + if(accessType !== 'edit'){ + brew.editId = undefined; } return brew; }; -const sanitizeMiddleware = (accessType)=>{ - return (req, res, next)=>{ - req.brew = sanitizeBrew(req.brew, accessType !== 'edit'); - return next(); - }; -}; - app.use('/', serveCompressedStaticAssets(`build`)); //app.use(express.static(`${__dirname}/build`)); @@ -105,8 +95,9 @@ app.get('/v3_preview', (req, res, next)=>{ text : welcomeTextV3, renderer : 'V3' }; + splitTextStyleAndMetadata(req.brew); return next(); -}, splitTextStyleAndMetadata); +}); //Legacy/Other Document -> v3 Migration Guide app.get('/migrate', (req, res, next)=>{ @@ -114,8 +105,9 @@ app.get('/migrate', (req, res, next)=>{ text : migrateText, renderer : 'V3' }; + splitTextStyleAndMetadata(req.brew); return next(); -}, splitTextStyleAndMetadata); +}); //Changelog page app.get('/changelog', async (req, res, next)=>{ @@ -124,8 +116,9 @@ app.get('/changelog', async (req, res, next)=>{ text : changelogText, renderer : 'V3' }; + splitTextStyleAndMetadata(req.brew); return next(); -}, splitTextStyleAndMetadata); +}); //FAQ page app.get('/faq', async (req, res, next)=>{ @@ -134,8 +127,9 @@ app.get('/faq', async (req, res, next)=>{ text : faqText, renderer : 'V3' }; + splitTextStyleAndMetadata(req.brew); return next(); -}, splitTextStyleAndMetadata); +}); //Source page app.get('/source/:id', asyncHandler(getBrew('share')), (req, res)=>{ @@ -151,8 +145,9 @@ app.get('/source/:id', asyncHandler(getBrew('share')), (req, res)=>{ }); //Download brew source page -app.get('/download/:id', asyncHandler(getBrew('share')), sanitizeMiddleware('share'), (req, res)=>{ +app.get('/download/:id', asyncHandler(getBrew('share')), (req, res)=>{ const { brew } = req; + sanitizeBrew(brew, 'share'); const prefix = 'HB - '; let fileName = sanitizeFilename(`${prefix}${brew.title}`).replaceAll(' ', ''); @@ -186,6 +181,9 @@ app.get('/user/:username', async (req, res, next)=>{ if(match !== -1) { brew.googleId = googleBrews[match].googleId; brew.stubbed = true; + brew.pageCount = googleBrews[match].pageCount; + brew.renderer = googleBrews[match].renderer; + brew.version = googleBrews[match].version; googleBrews.splice(match, 1); } } @@ -197,20 +195,26 @@ app.get('/user/:username', async (req, res, next)=>{ } req.brews = _.map(brews, (brew)=>{ - return sanitizeBrew(brew, !ownAccount); + return sanitizeBrew(brew, ownAccount ? 'edit' : 'share'); }); return next(); }); //Edit Page -app.get('/edit/:id', asyncHandler(getBrew('edit')), sanitizeMiddleware('edit'), splitTextStyleAndMetadata, (req, res, next)=>{ +app.get('/edit/:id', asyncHandler(getBrew('edit')), (req, res, next)=>{ + req.brew = req.brew.toObject ? req.brew.toObject() : req.brew; + sanitizeBrew(req.brew, 'edit'); + console.log('edit', req.brew); + splitTextStyleAndMetadata(req.brew); res.header('Cache-Control', 'no-cache, no-store'); //reload the latest saved brew when pressing back button, not the cached version before save. return next(); }); //New Page -app.get('/new/:id', asyncHandler(getBrew('share')), sanitizeMiddleware('share'), splitTextStyleAndMetadata, (req, res, next)=>{ +app.get('/new/:id', asyncHandler(getBrew('share')), (req, res, next)=>{ + sanitizeBrew(req.brew, 'share'); + splitTextStyleAndMetadata(req.brew); req.brew.title = `CLONE - ${brew.title}`; return next(); }); @@ -227,12 +231,17 @@ app.get('/share/:id', asyncHandler(getBrew('share')), asyncHandler(async (req, r } else { await HomebrewModel.increaseView({ shareId: brew.shareId }); } - + sanitizeBrew(req.brew, 'share'); + splitTextStyleAndMetadata(req.brew); return next(); -}), sanitizeMiddleware('share'), splitTextStyleAndMetadata); +})); //Print Page -app.get('/print/:id', asyncHandler(getBrew('share')), sanitizeMiddleware('share'), splitTextStyleAndMetadata); +app.get('/print/:id', asyncHandler(getBrew('share')), (req, res, next)=>{ + sanitizeBrew(req.brew, 'share'); + splitTextStyleAndMetadata(req.brew); + next(); +}); const nodeEnv = config.get('node_env'); const isLocalEnvironment = config.get('local_environments').includes(nodeEnv); diff --git a/server/googleActions.js b/server/googleActions.js index b7e490dd4..5d9e43b71 100644 --- a/server/googleActions.js +++ b/server/googleActions.js @@ -142,15 +142,13 @@ const GoogleActions = { name : `${brew.title}.txt`, description : `${brew.description}`, properties : { - 'title' : brew.title, - 'shareId' : brew.shareId || nanoid(12), - 'editId' : brew.editId || nanoid(12), - 'views' : brew.views, - 'pageCount' : brew.pageCount, - 'renderer' : brew.renderer || 'legacy', - 'isStubbed' : true, - 'updatedAt' : new Date().toISOString(), - thumbnail : brew.thumbnail + title : brew.title, + shareId : brew.shareId || nanoid(12), + editId : brew.editId || nanoid(12), + pageCount : brew.pageCount, + renderer : brew.renderer || 'legacy', + isStubbed : true, + thumbnail : brew.thumbnail } }, media : { @@ -178,20 +176,18 @@ const GoogleActions = { const folderId = await GoogleActions.getGoogleFolder(auth); const fileMetadata = { - 'name' : `${brew.title}.txt`, - 'description' : `${brew.description}`, - 'parents' : [folderId], - 'properties' : { //AppProperties is not accessible - 'shareId' : brew.shareId || nanoid(12), - 'editId' : brew.editId || nanoid(12), - 'title' : brew.title, - 'views' : '0', - 'pageCount' : brew.pageCount, - 'renderer' : brew.renderer || 'legacy', - 'isStubbed' : true, - 'createdAt' : new Date().toISOString(), - 'version' : 1, - 'thumbnail' : brew.thumbnail || '' + name : `${brew.title}.txt`, + description : `${brew.description}`, + parents : [folderId], + properties : { //AppProperties is not accessible + shareId : brew.shareId || nanoid(12), + editId : brew.editId || nanoid(12), + title : brew.title, + pageCount : brew.pageCount, + renderer : brew.renderer || 'legacy', + isStubbed : true, + version : 1, + thumbnail : brew.thumbnail || '' } }; diff --git a/server/homebrew.api.js b/server/homebrew.api.js index 688cb5a58..da8526fb9 100644 --- a/server/homebrew.api.js +++ b/server/homebrew.api.js @@ -14,48 +14,41 @@ const { nanoid } = require('nanoid'); // }); // }; -const findBrew = async (brewId, accessType, googleObjectId)=>{ - let id = brewId; - let googleId = googleObjectId; - if(id.length > 12) { - googleId = id.slice(0, -12); - id = id.slice(-12); - } - let brew = await HomebrewModel.get(accessType === 'edit' ? { editId: id } : { shareId: id }) - .catch((err)=>{ - if(googleId) { - console.warn(`Unable to find document stub for ${accessType}Id ${id}`); - } else { - console.warn(err); - } - }); - - let googleBrew; - if(googleId || brew?.googleId) { - googleBrew = await GoogleActions.getGoogleBrew(googleId || brew?.googleId, id, accessType) - .catch((err)=>{ - console.warn(err); - }); - if(!brew && !googleBrew) throw 'Brew not found in database or Google Drive'; - brew = brew ? _.merge(brew, googleBrew) : googleBrew; - } else if(!brew) { - throw 'Brew not found in database'; - } - - return brew; -}; - const getBrew = (accessType)=>{ return async (req, res, next)=>{ const { brew } = req; if(!brew) { - const id = req.params.id, googleId = req.body?.googleId; - const found = await findBrew(id, accessType, googleId); + let id = req.params.id, googleId = req.body?.googleId; + + if(id.length > 12) { + googleId = id.slice(0, -12); + id = id.slice(-12); + } + let found = await HomebrewModel.get(accessType === 'edit' ? { editId: id } : { shareId: id }) + .catch((err)=>{ + if(googleId) { + console.warn(`Unable to find document stub for ${accessType}Id ${id}`); + } else { + console.warn(err); + } + }); + + if(googleId || found?.googleId) { + const googleBrew = await GoogleActions.getGoogleBrew(googleId || found?.googleId, id, accessType) + .catch((err)=>{ + console.warn(err); + }); + if(!found && !googleBrew) throw 'Brew not found in database or Google Drive'; + found = found ? Object.assign(excludeStubProps(found), excludeGoogleProps(googleBrew)) : googleBrew; + } else if(!found) { + throw 'Brew not found in database'; + } + req.brew = accessType !== 'edit' && found.toObject ? found.toObject() : found; } - !!next ? next() : undefined; + next(); }; }; @@ -85,7 +78,7 @@ const getGoodBrewTitle = (text)=>{ const excludePropsFromUpdate = (brew)=>{ // Remove undesired properties - const propsToExclude = ['views', 'lastViewed', 'editId', 'shareId', 'googleId']; + const propsToExclude = ['_id', 'views', 'lastViewed', 'editId', 'shareId', 'googleId']; for (const prop of propsToExclude) { delete brew[prop]; } @@ -93,15 +86,16 @@ const excludePropsFromUpdate = (brew)=>{ }; const excludeStubProps = (brew)=>{ - const propsToExclude = ['text', 'textBin', 'renderer', 'pageCount', 'views', 'version']; + const propsToExclude = ['text', 'textBin', 'renderer', 'pageCount', 'version']; for (const prop of propsToExclude) { brew[prop] = undefined; } + return brew; }; const excludeGoogleProps = (brew)=>{ const modified = brew.toObject ? brew.toObject() : brew; - const propsToExclude = ['tags', 'systems', 'published', 'authors', 'owner']; + const propsToExclude = ['tags', 'systems', 'published', 'authors', 'owner', 'views']; for (const prop of propsToExclude) { delete modified[prop]; } @@ -173,6 +167,7 @@ const newBrew = async (req, res)=>{ }; const updateBrew = async (req, res)=>{ + console.log(req.brew, req.body); let brew = Object.assign(req.brew, excludePropsFromUpdate(req.body)); brew.text = mergeBrewText(brew); const { transferToGoogle, transferFromGoogle } = req.query;