diff --git a/api/index.js b/api/index.js index c9af6bf..6d88611 100644 --- a/api/index.js +++ b/api/index.js @@ -1,248 +1,43 @@ const express = require("express") -const {gimmeToken} = require("./util.js") const { MongoClient } = require("mongodb") require("dotenv").config() -// routes /* * error: 0 -> no error * error: 1 -> parameter error * error: 2 -> auth error * error: 3 -> not found error */ -const resources = require("./routes/resources.js") -const projects = require("./routes/projects.js") -const blog = require("./routes/blog.js") -const auth = require("./routes/auth.js") +const db = new MongoClient(process.env.DATABASE); const app = express() app.use(express.json()) app.use(express.urlencoded({ extended: false })); -app.use("/resources", resources) -app.use("/projects", projects) -app.use("/blog", blog) -app.use("/auth", auth) - -const db = new MongoClient(process.env.DATABASE); -const PASS = process.env.PASS -let TOKEN = gimmeToken(); - -app.use((req, res, next) => { - req.db = db; - next(); +app.use((req,res,next)=>{ + req.db = db + next() }) -// PATH: /api/login -// METHOD: GET -// PARAMETERS: pass -app.get("/login", (req,res)=>{ - let pass = req.query.pass; +const { auth, authware } = require("./routes/auth.js") +// anything starts with "add" +// requires admin privs +app.use("/*/a*", authware) +const resources = require("./routes/resources.js") +const projects = require("./routes/projects.js") +const blog = require("./routes/blog.js") +const routes = [ + resources, + projects, + blog, + auth, +] - if (pass === undefined) - return res.json({error: 1}) - - if (pass !== PASS) - return res.json({error: 2}) - - res.json({error: 0, token:TOKEN}) +routes.forEach(route=>{ + app.use(route.path, route) }) -// PATH: /api/logout -// METHOD: GET -// PARAMETERS: token -app.get("/logout", (req,res)=>{ - let token = req.query.token; - - if (token === undefined) - return res.json({error: 1}) - - if (token !== TOKEN) - return res.json({error: 2}) - - TOKEN = gimmeToken() - res.json({error: 0}) -}) - -// PATH: /api/add_project -// METHOD: GET -// PARAMETERS: token, name, desc, url -app.get("/add_project", async (req, res) => { - let token = req.query.token; - let name = req.query.name; - let desc = req.query.desc; - let url = req.query.url; - - if ( - token === undefined || - name === undefined || - desc === undefined || - url === undefined - ) - return res.json({error: 1}) - - if (token !== TOKEN) - return res.json({error: 2}) - - await client.connect() - const db = await client.db("ngn13") - const col = await db.collection("projects") - await col.insertOne({"name":name, "desc":desc, "url":url, "click":0}) - await client.close() - res.json({error: 0}) -}); - -// PATH: /api/add_resource -// METHOD: GET -// PARAMETERS: token, name, tags, url -app.get("/add_resource", async (req, res) => { - let token = req.query.token; - let name = req.query.name; - let tags = req.query.tags; - let url = req.query.url; - - if ( - token === undefined || - name === undefined || - tags === undefined || - url === undefined - ) - return res.json({error: 1}) - - if (token !== TOKEN) - return res.json({error: 2}) - - await client.connect() - const db = await client.db("ngn13") - const col = await db.collection("resources") - await col.insertOne({"name":name, "tags":tags.split(","), "url":url}) - await client.close() - res.json({error: 0}) -}); - -// PATH: /api/get_projects -// METHOD: GET -// PARAMETERS: NONE -app.get("/get_projects", async (req, res) => { - await client.connect() - const db = await client.db("ngn13") - const col = await db.collection("projects") - const array = await col.find().toArray() - await client.close() - res.json({error: 0, projects:array}) -}); - -// PATH: /api/get_resources -// METHOD: GET -// PARAMETERS: NONE -app.get("/get_resources", async (req, res) => { - await client.connect() - const db = await client.db("ngn13") - const col = await db.collection("resources") - const array = await col.find().toArray() - await client.close() - res.json({error: 0, resources:array}) -}); - -// PATH: /api/get_resources -// METHOD: GET -// PARAMETERS: NONE -app.get("/get_resources", async (req, res) => { - await client.connect() - const db = await client.db("ngn13") - const col = await db.collection("resources") - const array = await col.find().toArray() - await client.close() - res.json({error: 0, resources:array}) -}); - -// PATH: /api/add_post -// METHOD: POST -// PARAMETERS: token, title, author, content -app.post("/add_post", async (req, res) => { - let token = req.body.token; - let title = req.body.title; - let author = req.body.author; - let content = req.body.content; - - if ( - token === undefined || - title === undefined || - author === undefined || - content === undefined - ) - return res.json({error: 1}) - - if (token !== TOKEN) - return res.json({error: 2}) - - await client.connect() - const db = await client.db("ngn13") - const col = await db.collection("posts") - await col.insertOne({ - "title":title, - "author":author, - "date": new Date().toLocaleDateString(), - "content":content - }) - await client.close() - res.json({error: 0}) -}); - -// PATH: /api/get_posts -// METHOD: POST -// PARAMETERS: NONE -app.get("/get_posts", async (req, res) => { - await client.connect() - const db = await client.db("ngn13") - const col = await db.collection("posts") - const array = await col.find().toArray() - await client.close() - - let newarray = [] - for(let i = 0;i { - let id = req.query.id; - - await client.connect() - const db = await client.db("ngn13") - const col = await db.collection("posts") - const array = await col.find().toArray() - await client.close() - - for(let i = 0;i { - res.send({ error: 0 }); -}); export default { path: "/api", handler: app, -}; +} diff --git a/api/routes/auth.js b/api/routes/auth.js new file mode 100644 index 0000000..1304807 --- /dev/null +++ b/api/routes/auth.js @@ -0,0 +1,39 @@ +const express = require("express") +const { gimmeToken } = require("../util.js") +const auth = express.Router() +auth.path = "/auth" + +const PASS = process.env.PASS +let TOKEN = gimmeToken(); + +function authware(req,res,next){ + const token = req.query.token ? req.query.token : req.body.token + + if(!token) + return res.json({ error: 1 }) + + if(token!==TOKEN) + return res.json({ error: 2 }) + + next() +} +auth.use("/logout", authware) + +auth.get("/login", async (req,res)=>{ + const pass = req.query.pass + + if(!pass) + return res.json({ error: 1 }) + + if(pass!==PASS) + return res.json({ error: 2 }) + + res.json({ error: 0, token: TOKEN }) +}) + +auth.get("/logout", async (req,res)=>{ + TOKEN = gimmeToken() + res.json({ error: 0 }) +}) + +module.exports = { auth, authware } diff --git a/api/routes/blog.js b/api/routes/blog.js new file mode 100644 index 0000000..10363bd --- /dev/null +++ b/api/routes/blog.js @@ -0,0 +1,93 @@ +const express = require("express") +const { makeID } = require("../util.js") +const blog = express.Router() +blog.path = "/blog" + +blog.get("/sum", async (req,res)=>{ + await req.db.connect() + const db = await req.db.db("ngn13") + const col = await db.collection("posts") + const results = await col.find({priv: {$eq: false}}).toArray() + await req.db.close() + + let posts = [] + for(let i = 0;i{ + const id = req.query.id + + await req.db.connect() + const db = await req.db.db("ngn13") + const col = await db.collection("posts") + const results = await col.find().toArray() + await req.db.close() + + for(let i = 0;i onlineprivacyguide + if(makeID(results[i]["title"])===id){ + return res.json( + { + error: 0, + post:{ + "title": results[i]["title"], + // info is the subtitle, for example: + // ngn | 01/06/2023 + "info": `${results[i]["author"]} | ${results[i]["date"]}`, + "content": results[i]["content"], + } + } + ) + } + } + + res.json({ error: 3 }) + +}) + +blog.post("/add", async (req,res)=>{ + console.log("heyy") + const title = req.body.title + const author = req.body.author + const content = req.body.content + const priv = req.body.priv + console.log(title, author, content, priv) + + if ( !title || !author || !content || !priv ) + return res.json({ error: 1 }) + + await req.db.connect() + const db = await req.db.db("ngn13") + const col = await db.collection("posts") + await col.insertOne({ + "title":title, + "author":author, + "date": new Date().toLocaleDateString(), + "content":content, + "priv": priv + }) + await req.db.close() + res.json({ error: 0 }) +}) + +module.exports = blog diff --git a/api/routes/projects.js b/api/routes/projects.js new file mode 100644 index 0000000..9ea5140 --- /dev/null +++ b/api/routes/projects.js @@ -0,0 +1,35 @@ +const express = require("express") +const projects = express.Router() +projects.path = "/projects" + +projects.get("/get", async (req,res)=>{ + await req.db.connect() + const db = await req.db.db("ngn13") + const col = await db.collection("projects") + const results = await col.find().toArray() + await req.db.close() + res.json({ error: 0, projects: results }) +}) + +projects.get("/add", async (req,res)=>{ + let name = req.query.name; + let desc = req.query.desc; + let url = req.query.url; + + if (!name || !desc || !url ) + return res.json({ error: 1 }) + + await req.db.connect() + const db = await req.db.db("ngn13") + const col = await db.collection("projects") + await col.insertOne({ + "name":name, + "desc":desc, + "url":url, + "click":0 + }) + await req.db.close() + res.json({ error: 0 }) +}) + +module.exports = projects diff --git a/api/routes/resources.js b/api/routes/resources.js index 2cfd1cc..06173df 100644 --- a/api/routes/resources.js +++ b/api/routes/resources.js @@ -1,12 +1,34 @@ const express = require("express") const resources = express.Router() +resources.path = "/resources" resources.get("/get", async (req,res)=>{ await req.db.connect() - const col = await req.db.collection("ngn13") - const results = col.find().limit(10).toArray() + const db = await req.db.db("ngn13") + const col = await db.collection("resources") + let results = [] + if(req.query.sum) + results = await col.find().limit(10).toArray() + else + results = await col.find().toArray() await req.db.close() res.json({ error: 0, resources: results }) }) +resources.get("/add", async (req,res)=>{ + let name = req.query.name; + let tags = req.query.tags; + let url = req.query.url; + + if(!name || !tags || !url) + return res.json({"error":1}) + + await req.db.connect() + const db = await req.db.db("ngn13") + const col = await db.collection("resources") + await col.insertOne({"name":name, "tags":tags.split(","), "url":url}) + await req.db.close() + res.json({error: 0}) +}) + module.exports = resources diff --git a/api/util.js b/api/util.js index fe1af4f..878748b 100644 --- a/api/util.js +++ b/api/util.js @@ -8,5 +8,15 @@ function gimmeToken() { return result; } -module.exports = {gimmeToken} +function makeID(title){ + // this is used in blog.js + // id is basically the title of the post + // but ve remove the whitespace + // and make it lowerspace + // for example: + // Online Privacy Guide -> onlineprivacyguide + return title.toLowerCase().replaceAll(" ", "") +} + +module.exports = { gimmeToken, makeID } diff --git a/components/Logout.vue b/components/Logout.vue index 1fca207..d3d2682 100644 --- a/components/Logout.vue +++ b/components/Logout.vue @@ -12,7 +12,7 @@ import Button from './Button.vue'; export default { methods: { async click(e) { - await axios.get(`/api/logout?token=${localStorage.getItem("token")}`) + await axios.get(`/api/auth/logout?token=${localStorage.getItem("token")}`) localStorage.clear() location.reload() } @@ -38,4 +38,4 @@ div{ align-items: center; justify-content: center; } - \ No newline at end of file + diff --git a/components/NewPost.vue b/components/NewPost.vue index be3d922..8907ac6 100644 --- a/components/NewPost.vue +++ b/components/NewPost.vue @@ -4,11 +4,12 @@
+

+ Make the post private + +

-
- - -
+ @@ -23,17 +24,15 @@ export default { async click(e) { const title = document.getElementById("title").value const author = document.getElementById("author").value - const contenten = document.getElementById("contenten").value - const contenttr = document.getElementById("contenttr").value + const content = document.getElementById("content").value + const priv = document.getElementById("private").value const token = localStorage.getItem("token") - const res = await axios.post("/api/add_post", { + const res = await axios.post("/api/blog/add", { token: token, title: title, author: author, - content: { - tr: contenttr, - en: contenten - }, + content: content, + priv: priv==="on" }) if(res.data["error"]!==0) return alert("Error!") @@ -52,9 +51,29 @@ h1{ text-align: center; } +h2{ + background: var(--dark-two); + font-size: 25px; + border-radius: 20px; + border: none; + padding: 20px; + color: var(--white); + display: flex; + justify-content: space-between; +} + +input[type="checkbox"] { + -ms-transform: scale(2); + -moz-transform: scale(2); + -webkit-transform: scale(2); + -o-transform: scale(2); + transform: scale(2); + padding: 10px; +} + textarea{ width: 500px; - font-size: 15px; + font-size: 20px; padding: 20px; border-radius: 20px; background: var(--dark-two); @@ -67,7 +86,7 @@ textarea{ } .textareas { - flex-direction: row; + flex-direction: column; display: flex; gap: 20px; } @@ -86,4 +105,4 @@ main{ align-items: center; justify-content: center; } - \ No newline at end of file + diff --git a/components/NewProject.vue b/components/NewProject.vue index 3202531..b9e3458 100644 --- a/components/NewProject.vue +++ b/components/NewProject.vue @@ -20,7 +20,7 @@ export default { const desc = document.getElementById("desc").value const url = document.getElementById("url").value const token = localStorage.getItem("token") - const res = await axios.get(`/api/add_project?token=${token}&name=${name}&desc=${desc}&url=${url}`) + const res = await axios.get(`/api/projects/add?token=${token}&name=${name}&desc=${desc}&url=${url}`) if(res.data["error"]!==0) return alert("Error!") alert("Project added!") @@ -48,4 +48,4 @@ div{ align-items: center; justify-content: center; } - \ No newline at end of file + diff --git a/components/NewResource.vue b/components/NewResource.vue index edb695b..59bdc47 100644 --- a/components/NewResource.vue +++ b/components/NewResource.vue @@ -20,7 +20,7 @@ export default { const tags = document.getElementById("tags").value const url = document.getElementById("url").value const token = localStorage.getItem("token") - const res = await axios.get(`/api/add_resource?token=${token}&name=${name}&tags=${tags}&url=${url}`) + const res = await axios.get(`/api/resources/add?token=${token}&name=${name}&tags=${tags}&url=${url}`) if(res.data["error"]!==0) return alert("Error!") alert("Resource added!") @@ -48,4 +48,4 @@ div{ align-items: center; justify-content: center; } - \ No newline at end of file + diff --git a/links/index.js b/links/index.js index b67f989..5428467 100644 --- a/links/index.js +++ b/links/index.js @@ -1,5 +1,6 @@ const express = require("express"); const { MongoClient } = require("mongodb"); +const { makeID } = require("../api/util.js") require("dotenv").config() const app = express(); @@ -10,20 +11,20 @@ const client = new MongoClient(process.env.DATABASE); app.get("/:id", async (req,res)=>{ const id = req.params.id - + await client.connect() const db = await client.db("ngn13") const col = await db.collection("projects") const projects = await col.find().toArray() - + console.log(projects) for(let i=0; i{ export default { path: "/l", handler: app, -}; +} diff --git a/nuxt.config.js b/nuxt.config.js index 76eaf6d..8b9daa7 100644 --- a/nuxt.config.js +++ b/nuxt.config.js @@ -14,10 +14,9 @@ export default { { hid: "og:url", content: "https://ngn13.fun" }, { name: "theme-color", content: "#141414", "data-react-helmet":"true"}, ], - + link: [ { rel: "stylesheet", href: "https://unpkg.com/boxicons@2.1.4/css/boxicons.min.css" }, - { rel: "stylesheet", href: "https://cdn.jsdelivr.net/gh/lipis/flag-icons@6.6.6/css/flag-icons.min.css" } ] }, css: ["@/static/global.css"], diff --git a/pages/blog/_id/index.vue b/pages/blog/_id/index.vue index 374814c..9b297f4 100644 --- a/pages/blog/_id/index.vue +++ b/pages/blog/_id/index.vue @@ -6,14 +6,7 @@

{{ post.info }}

-
- - - - -
-
-
+
@@ -39,30 +32,24 @@ export default { }; }, - methods: { - toggle_lang(){ - this.lang = this.lang==="tr" ? "en" : "tr" - localStorage.setItem("lang", this.lang) - } - }, data() { return { post: {}, lang: "", - en: "", - tr: "", + content: "", } }, async created() { - const res = await axios.get(`/api/get_post?id=${this.$route.params.id}`) + const res = await axios.get(`/api/blog/get?id=${this.$route.params.id}`) if (res.data["error"] === 3) return this.$router.push({ path: "/blog" }) this.post = res.data["post"] - this.en = DOMPurify.sanitize(marked.parse(this.post["content"]["en"])) - this.tr = DOMPurify.sanitize(marked.parse(this.post["content"]["tr"])) - this.lang = localStorage.getItem("lang")!==undefined&&(localStorage.getItem("lang")==="tr"||localStorage.getItem("lang")==="en") ? localStorage.getItem("lang") : "en" + this.content = DOMPurify.sanitize( + marked.parse(this.post["content"], { breaks: true }), + { ADD_TAGS: ["iframe"], ADD_ATTR: ['allow', 'allowfullscreen', 'frameborder', 'scrolling'] } + ) } } @@ -77,11 +64,6 @@ p { font-size: 30px; } -span{ - width: 30px; - border-radius: 5px; -} - .info { display: flex; flex-direction: row; @@ -89,90 +71,39 @@ span{ justify-content: center; } -.lang { - display: flex; - flex-direction: row; - align-items: center; - justify-content: center; - margin-top: 20px; -} - -button{ - padding: 10px 30px 10px 30px; - font-size: 20px; - background-color: var(--dark-two); - border: none; - cursor: pointer; - color: white -} -.bs{ - background-color: var(--dark-three); -} -.bl{ - border-radius: 15px 0px 0px 0px; -} - -.br{ - border-radius: 0px 15px 0px 0px; -} - .postcontain{ padding: 50px; } -.postself { - text-align: left; - font-size: 30px; - color: white; - padding: 20px 40px 70px 40px; - line-height: 40px; +.markdown-body { + font-size: 25px; + padding: 50px; border-radius: 15px; background-color: var(--dark-three); } \ No newline at end of file + diff --git a/pages/blog/index.vue b/pages/blog/index.vue index d962f11..ccaf469 100644 --- a/pages/blog/index.vue +++ b/pages/blog/index.vue @@ -6,7 +6,7 @@
- + {{ post.desc }}
@@ -44,33 +44,31 @@ export default { mounted: async function () { if (localStorage.getItem("token")) this.logged = true; - const res = await axios.get("/api/get_posts"); + const res = await axios.get("/api/blog/sum"); + let posts = [] - let array = res.data["posts"] - let newarray = [] - - for(let i=0;i{ + posts.push({ + title: post.title, + desc: post.desc, + info: post.info, + url: `/blog/${post.title.toLowerCase().replaceAll(" ", "")}` }) - } + }) - this.posts = newarray; - this.all = newarray; + this.posts = posts + this.all = posts }, methods: { keyup(e) { let val = e.target.value - + // search looks at name and info this.posts = [] for(let i = 0; i < this.all.length; i++){ if(this.all[i].title.toLowerCase().includes(val.toLowerCase())) this.posts.push(this.all[i]) - + else if(this.all[i].info.toLowerCase().includes(val.toLowerCase())) this.posts.push(this.all[i]) } @@ -88,4 +86,4 @@ export default { gap: 30px; align-items: center; } - \ No newline at end of file + diff --git a/pages/login.vue b/pages/login.vue index 09df0b5..1bd9cbf 100644 --- a/pages/login.vue +++ b/pages/login.vue @@ -15,7 +15,7 @@ export default { methods: { async click(e) { const pass = document.getElementById("pass").value - const res = await axios.get(`/api/login?pass=${pass}`) + const res = await axios.get(`/api/auth/login?pass=${pass}`) if(res.data["error"]===0){ localStorage.setItem("token", res.data["token"]) return location.href="/" @@ -48,4 +48,4 @@ h1{ font-size: 70px; margin-bottom: 20px; } - \ No newline at end of file + diff --git a/pages/projects.vue b/pages/projects.vue index cb8df0d..00bfd73 100644 --- a/pages/projects.vue +++ b/pages/projects.vue @@ -35,16 +35,16 @@ export default { }, data() { return { - logged: false, - projects: [] + logged: false, + projects: [] } }, mounted: async function(){ if(localStorage.getItem("token")) this.logged = true - const res = await axios.get("/api/get_projects") - + const res = await axios.get("/api/projects/get") + let all = res.data["projects"] let projects = [] let project = [] @@ -82,4 +82,4 @@ export default { padding: 50px; } } - \ No newline at end of file + diff --git a/pages/resources.vue b/pages/resources.vue index 47180e8..6c1b893 100644 --- a/pages/resources.vue +++ b/pages/resources.vue @@ -6,7 +6,7 @@
- +
@@ -35,44 +35,59 @@ export default { return { header: "resources", logged: false, - resources: [], - all: [] + sum_resources: [], + all_resources: [], + show_resources: [] } }, methods: { keyup(e) { - let val = e.target.value - if(e.key==="Backspace" && val===""){ + let search = e.target.value + if(e.key==="Backspace" && search===""){ this.header = "resources" - this.resources = this.all + this.show_resources = this.sum_resources return } if(e.key==="OS") return - this.header = `resources | grep ${val}` + this.header = `resources | grep ${search}` // dirty asf search alg - this.resources = [] - for(let i = 0; i < this.all.length; i++){ - if(this.all[i].name.toLowerCase().includes(val.toLowerCase())) - this.resources.push(this.all[i]) - - for(let e = 0; e < this.all[i].tags.length; e++){ - if(this.all[i].tags[e].toLowerCase().includes(val.toLowerCase())){ - if(this.resources.indexOf(this.all[i])===-1) - this.resources.push(this.all[i]) + this.show_resources = [] + for(let i = 0; i < this.all_resources.length; i++){ + if(this.all_resources[i].name + .toLowerCase() + .includes(search.toLowerCase()) + ){ + this.show_resources.push(this.all_resources[i]) + continue + } + + for(let e = 0; e < this.all_resources[i].tags.length; e++){ + if(this.all_resources[i].tags[e].toLowerCase() + .includes(search.toLowerCase()) + ){ + this.show_resources.push(this.all_resources[i]) + break } } } - } + } }, mounted: async function(){ - if(localStorage.getItem("token")) + if(localStorage.getItem("token")) this.logged = true - const res = await axios.get("/api/get_resources") - this.resources = res.data["resources"] - this.all = res.data["resources"] + // request top 10 resources so we can + // render the DOM as fast as possible + let res = await axios.get("/api/resources/get?sum=1") + this.sum_resources = res.data["resources"] + this.show_resources = this.sum_resources + + // then we can load all the resources + res = await axios.get("/api/resources/get") + this.all_resources = res.data["resources"] + console.log(res.data["resources"]) } } @@ -86,4 +101,4 @@ export default { align-items: center; gap: 40px } - \ No newline at end of file +