From e8135fcbb4ea5b1a04c7a2dc3e5089ca75388929 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Thu, 21 Jan 2021 00:02:15 +1300 Subject: [PATCH] Added `sanitizeHtml` function to Homebrew model to generate HTML from the brew for the source page. Moved `source` page generation function to a new function module. Added option to function to create plain text download with a sanitized filename and made it accessible from a new page: `download`. Added the `download` item to the BrewItem so it appears on each brew on the User page. Added `sanitize-filename` dependency to `package.json`. --- client/homebrew/pages/sharePage/sharePage.jsx | 2 +- .../pages/sharePage/sourceFunctions.jsx | 56 +++++++++++++++++++ client/homebrew/pages/sharePage/source_dl.jsx | 14 ----- .../pages/userPage/brewItem/brewItem.jsx | 9 +-- package.json | 1 + server.js | 53 ++---------------- server/homebrew.model.js | 11 ++++ 7 files changed, 79 insertions(+), 67 deletions(-) create mode 100644 client/homebrew/pages/sharePage/sourceFunctions.jsx delete mode 100644 client/homebrew/pages/sharePage/source_dl.jsx diff --git a/client/homebrew/pages/sharePage/sharePage.jsx b/client/homebrew/pages/sharePage/sharePage.jsx index 9867e9dc3..863cc2aa2 100644 --- a/client/homebrew/pages/sharePage/sharePage.jsx +++ b/client/homebrew/pages/sharePage/sharePage.jsx @@ -62,7 +62,7 @@ const SharePage = createClass({ view source - + download source diff --git a/client/homebrew/pages/sharePage/sourceFunctions.jsx b/client/homebrew/pages/sharePage/sourceFunctions.jsx new file mode 100644 index 000000000..a52b08d19 --- /dev/null +++ b/client/homebrew/pages/sharePage/sourceFunctions.jsx @@ -0,0 +1,56 @@ +const HomebrewModel = require.main.require('./server/homebrew.model.js').model; +const sanitizeFilename = require('sanitize-filename'); + +const shareFunction = function(req, res, type) { + 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)=>{ + if(type == 'source') { + return res.status(200).send(brew.sanitizeHtml()); + } else if(type == 'download') { + let fileName = sanitizeFilename(brew.title); + fileName = fileName.replaceAll(' ', '-'); + res.status(200); + res.set({ + 'Cache-Control' : 'no-cache', + 'Content-Type' : 'text/plain', + 'Content-Disposition' : `attachment; filename="HomeBrewery-${fileName}.txt"` + }); + return res.send(brew.text); + } else { + console.log('Unhandled source share type'); + } + }) + .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)=>{ + if(type == 'source') { + return res.status(200).send(brew.sanitizeHtml()); + } else if(type == 'download') { + let fileName = sanitizeFilename(brew.title); + fileName = fileName.replaceAll(' ', '-'); + res.status(200); + res.set({ + 'Cache-Control' : 'no-cache', + 'Content-Type' : 'text/plain', + 'Content-Disposition' : `attachment; filename="HomeBrewery-${fileName}.txt"` + }); + return res.send(brew.text); + } else { + console.log('Unhandled share type'); + } + }) + .catch((err)=>{ + console.log(err); + return res.status(404).send('Could not find Homebrew with that id'); + }); + } +}; + +module.exports = shareFunction; \ No newline at end of file diff --git a/client/homebrew/pages/sharePage/source_dl.jsx b/client/homebrew/pages/sharePage/source_dl.jsx deleted file mode 100644 index e37ed9be4..000000000 --- a/client/homebrew/pages/sharePage/source_dl.jsx +++ /dev/null @@ -1,14 +0,0 @@ -const sourceDL = function(res, brew) { - const fileName = brew.title.replaceAll(' ', '-').replaceAll(':', '').replaceAll('/', ''); - - res.status(200); - res.set({ - 'Cache-Control' : 'no-cache', - 'Content-Type' : 'text/plain', - 'Content-Disposition' : `attachment; filename="HomeBrewery-${fileName}.txt"` - }); - - return res; -}; - -module.exports = sourceDL; \ No newline at end of file diff --git a/client/homebrew/pages/userPage/brewItem/brewItem.jsx b/client/homebrew/pages/userPage/brewItem/brewItem.jsx index bddf246bf..24d3e890e 100644 --- a/client/homebrew/pages/userPage/brewItem/brewItem.jsx +++ b/client/homebrew/pages/userPage/brewItem/brewItem.jsx @@ -65,7 +65,7 @@ const BrewItem = createClass({ ; }, - renderShareLink : function(){ + renderSourceLink : function(path, icon){ if(!this.props.brew.shareId) return; let shareLink = this.props.brew.shareId; @@ -73,8 +73,8 @@ const BrewItem = createClass({ shareLink = this.props.brew.googleId + shareLink; } - return - + return + ; }, @@ -107,8 +107,9 @@ const BrewItem = createClass({
- {this.renderShareLink()} + {this.renderSourceLink('share', 'fa-share-alt')} {this.renderEditLink()} + {this.renderSourceLink('download', 'fa-download')} {this.renderDeleteBrewLink()}
; diff --git a/package.json b/package.json index f5b7aff26..887c97715 100644 --- a/package.json +++ b/package.json @@ -66,6 +66,7 @@ "react-dom": "^16.14.0", "react-frame-component": "4.1.3", "react-router-dom": "5.2.0", + "sanitize-filename": "1.6.3", "superagent": "^6.1.0", "vitreum": "github:calculuschild/vitreum#21a8e1c9421f1d3a3b474c12f480feb2fbd28c5b" }, diff --git a/server.js b/server.js index dfd14580c..c0ea06c96 100644 --- a/server.js +++ b/server.js @@ -7,6 +7,8 @@ const app = express(); const homebrewApi = require('./server/homebrew.api.js'); const GoogleActions = require('./server/googleActions.js'); +const shareFunction = require ('./client/homebrew/pages/sharePage/sourceFunctions.jsx'); + // Serve brotli-compressed static files if available app.use('/', expressStaticGzip(`${__dirname}/build`, { enableBrotli : true, @@ -70,57 +72,12 @@ app.get('/robots.txt', (req, res)=>{ //Source page app.get('/source/:id', (req, res)=>{ - 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)=>{ - const text = brew.text.replaceAll('<', '<').replaceAll('>', '>'); - return 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 text = brew.text.replaceAll('<', '<').replaceAll('>', '>'); - return res.status(200).send(`
${text}
`); - }) - .catch((err)=>{ - console.log(err); - return res.status(404).send('Could not find Homebrew with that id'); - }); - } + return shareFunction(req, res, 'source'); }); //Source download page -app.get('/source_dl/:id', (req, res)=>{ - const sourceDL = require ('./client/homebrew/pages/sharePage/source_dl.jsx'); - 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)=>{ - res = sourceDL(res, brew); - return res.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)=>{ - res = sourceDL(res, brew); - return res.send(brew.text); - }) - .catch((err)=>{ - console.log(err); - return res.status(404).send('Could not find Homebrew with that id'); - }); - } +app.get('/download/:id', (req, res)=>{ + return shareFunction(req, res, 'download'); }); //User Page diff --git a/server/homebrew.model.js b/server/homebrew.model.js index 05a9ab673..05b94663a 100644 --- a/server/homebrew.model.js +++ b/server/homebrew.model.js @@ -34,6 +34,17 @@ HomebrewSchema.methods.sanatize = function(full=false){ return brew; }; +HomebrewSchema.methods.sanitizeHtml = function(){ + const brew = this.toJSON(); + const replaceStrings = { '&': '&', '<': '<', '>': '>' }; + text = brew.text; + for (const replaceStr in replaceStrings) { + text = text.replaceAll(replaceStr, replaceStrings[replaceStr]); + } + text = `
${text}
`; + return text; +}; + HomebrewSchema.methods.increaseView = async function(){ this.lastViewed = new Date(); this.views = this.views + 1;