diff --git a/express_backend/database.db b/express_backend/database.db index 57d94fc..9e04cfc 100644 Binary files a/express_backend/database.db and b/express_backend/database.db differ diff --git a/express_backend/securePostData.js b/express_backend/securePostData.js new file mode 100644 index 0000000..6522bf3 --- /dev/null +++ b/express_backend/securePostData.js @@ -0,0 +1,13 @@ +function secure(text){ + text = text.replace(/'/g, "\\u0027"); + return text; +} + +function decode(text){ + text = text.replace(/\\u0027/g, "'"); + return text; +} + +module.exports = { + secure, decode +} \ No newline at end of file diff --git a/express_backend/server.js b/express_backend/server.js index 3d3702d..7a37905 100644 --- a/express_backend/server.js +++ b/express_backend/server.js @@ -4,7 +4,7 @@ const app = express(); const sqlite3 = require('sqlite3'); const db = new sqlite3.Database("database.db") const port = process.env.PORT || 5000; - +const securePostData = require('./securePostData'); // body parser const bodyParser = require('body-parser'); app.use(bodyParser.json()); @@ -29,7 +29,11 @@ app.get('/idea/:id', (req, res) => { res.send({title: "Error", content: "Error fetching idea"}); }else{ if(rows.length > 0){ - res.json(rows[0]); + // De-Formatting + rows[0].title = securePostData.decode(rows[0].title); + rows[0].content = securePostData.decode(rows[0].content); + + res.json(rows[0]); }else{ res.send({title: "Error", content: "Idea not found"}); } @@ -42,6 +46,11 @@ app.get('/ideas', (req, res) => { if (err) { res.send({title: "Error", content: "Error fetching ideas"}); }else{ + for (let i = 0; i < rows.length; i++) { + // De-Formatting + rows[i].title = securePostData.decode(rows[i].title); + rows[i].content = securePostData.decode(rows[i].content); + } res.json(rows); } }); @@ -49,11 +58,40 @@ app.get('/ideas', (req, res) => { app.post('/idea/update/:id', (req, res) => { - db.run(`UPDATE ideas SET title = '${req.body.title}', content = '${req.body.content}' WHERE id = ${req.params.id}`, (err) => { + + // Validate POST + if(!req.body.title || req.body.title.replace(/\s/g, '').length === 0){ + res.send({title: "Error", type:"title", message: "Title is required"}); + return; + }else if(!req.body.content || req.body.content.replace(/\s/g, '').length === 0){ + res.send({title: "Error", type:"content", message: "Content is required"}); + return; + } + + let regexPattern = /^[a-zA-ZÀ-úÀ-ÿÀ-ÿÀ-ÖØ-öø-ÿ0-9ßäöüÄÖÜ!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?`´\s]*$/; + + + if(!regexPattern.test(req.body.title)){ + res.send({title: "Error", type:"title", message: "Title contains invalid characters"}); + return; + }else if(!regexPattern.test(req.body.content)){ + res.send({title: "Error", type:"content", message: "Content contains invalid characters"}); + return; + } + + // replace ' with \u0027 + let title = securePostData.secure(req.body.title); + let content = securePostData.secure(req.body.content); + + + + + + db.run(`UPDATE ideas SET title = '${title}', content = '${content}' WHERE id = ${req.params.id}`, (err) => { if (err) { - res.send({title: "Error", content: "Error updating idea"}); + res.send({title: "Error", type:"saving", message: "Error updating idea"}); }else{ - res.send({title: "Success", content: "Idea updated"}); + res.send({title: "Success", type:"saving", message: "Idea updated"}); } }); }); \ No newline at end of file diff --git a/react_frontend/src/IdeaContent.js b/react_frontend/src/IdeaContent.js index c6ea322..005d836 100644 --- a/react_frontend/src/IdeaContent.js +++ b/react_frontend/src/IdeaContent.js @@ -7,25 +7,28 @@ function IdeaContent(){ let [title, setTitle] = useState(""); let [content, setContent] = useState("") let [saved , setSaved] = useState(false); - let [seconds, setSeconds] = useState(0); + let [intervalTime, setintervalTime] = useState(0); + let [contentError, setContentError] = useState(""); + let [titleError, setTitleError] = useState(""); - let secondsSaveInterval = 3; + + //let secondsSaveInterval = 0; // TIMER useEffect(() => { const interval = setInterval(() => { - setSeconds(seconds => seconds + 1); + setintervalTime(intervalTime => intervalTime + 1); - if(seconds > secondsSaveInterval){ // save every > secondsSaveInterval seconds + if(intervalTime > 0){ saveData(); - setSeconds(0); + setintervalTime(0); } - }, 1000); + }, 500); return () => clearInterval(interval); }); - + const saveData = async () => { let ideaData = { title: title, @@ -44,7 +47,18 @@ function IdeaContent(){ if(res.title === "Success"){ setSaved(true); - } else { + setContentError(""); + setTitleError(""); + } else if(res.title === "Error"){ + if(res.type === "content"){ + setContentError(res.message); + setTitleError(""); + } else if(res.type === "title"){ + setTitleError(res.message); + setContentError(""); + } + setSaved(false); + }else{ setSaved(false); } } @@ -69,14 +83,20 @@ function IdeaContent(){ return(