diff options
author | Akshay <[email protected]> | 2024-11-13 22:34:03 +0000 |
---|---|---|
committer | Akshay <[email protected]> | 2024-11-13 22:34:03 +0000 |
commit | bbe0413ae1aad2516745f6f279225d2aea3555af (patch) | |
tree | 609fc751fb153f9fc0e3fbf111b644d5df5b1025 /src/routes/index.js | |
parent | 81adffe4c1ecd2f0260ec08e73760505dfe4edaa (diff) |
add login and users and all the pizzazz
Diffstat (limited to 'src/routes/index.js')
-rw-r--r-- | src/routes/index.js | 234 |
1 files changed, 149 insertions, 85 deletions
diff --git a/src/routes/index.js b/src/routes/index.js index d517ba2..7e68636 100644 --- a/src/routes/index.js +++ b/src/routes/index.js | |||
@@ -2,19 +2,21 @@ const express = require("express"); | |||
2 | const he = require("he"); | 2 | const he = require("he"); |
3 | const { hash, compare } = require("bun"); | 3 | const { hash, compare } = require("bun"); |
4 | const jwt = require("jsonwebtoken"); | 4 | const jwt = require("jsonwebtoken"); |
5 | const router = express.Router(); | ||
6 | const secretKey = "your_secret_key"; // Replace with your actual secret key | ||
7 | const geddit = require("../geddit.js"); | 5 | const geddit = require("../geddit.js"); |
8 | const { db } = require("../index"); | 6 | const { JWT_KEY } = require("../"); |
7 | const { db } = require("../db"); | ||
8 | const { authenticateToken } = require("../auth"); | ||
9 | |||
10 | const router = express.Router(); | ||
9 | const G = new geddit.Geddit(); | 11 | const G = new geddit.Geddit(); |
10 | 12 | ||
11 | // GET / | 13 | // GET / |
12 | router.get("/", async (req, res) => { | 14 | router.get("/", authenticateToken, async (req, res) => { |
13 | res.render("home"); | 15 | res.render("home"); |
14 | }); | 16 | }); |
15 | 17 | ||
16 | // GET /r/:id | 18 | // GET /r/:id |
17 | router.get("/r/:subreddit", async (req, res) => { | 19 | router.get("/r/:subreddit", authenticateToken, async (req, res) => { |
18 | const subreddit = req.params.subreddit; | 20 | const subreddit = req.params.subreddit; |
19 | const isMulti = subreddit.includes("+"); | 21 | const isMulti = subreddit.includes("+"); |
20 | const query = req.query ? req.query : {}; | 22 | const query = req.query ? req.query : {}; |
@@ -22,16 +24,33 @@ router.get("/r/:subreddit", async (req, res) => { | |||
22 | query.sort = "hot"; | 24 | query.sort = "hot"; |
23 | } | 25 | } |
24 | 26 | ||
27 | let isSubbed = false; | ||
28 | if (!isMulti) { | ||
29 | isSubbed = | ||
30 | db | ||
31 | .query( | ||
32 | "SELECT * FROM subscriptions WHERE user_id = $id AND subreddit = $subreddit", | ||
33 | ) | ||
34 | .get({ id: req.user.id, subreddit }) !== null; | ||
35 | } | ||
25 | const postsReq = G.getSubmissions(query.sort, `${subreddit}`, query); | 36 | const postsReq = G.getSubmissions(query.sort, `${subreddit}`, query); |
26 | const aboutReq = G.getSubreddit(`${subreddit}`); | 37 | const aboutReq = G.getSubreddit(`${subreddit}`); |
27 | 38 | ||
28 | const [posts, about] = await Promise.all([postsReq, aboutReq]); | 39 | const [posts, about] = await Promise.all([postsReq, aboutReq]); |
29 | 40 | ||
30 | res.render("index", { subreddit, posts, about, query, isMulti }); | 41 | res.render("index", { |
42 | subreddit, | ||
43 | posts, | ||
44 | about, | ||
45 | query, | ||
46 | isMulti, | ||
47 | user: req.user, | ||
48 | isSubbed, | ||
49 | }); | ||
31 | }); | 50 | }); |
32 | 51 | ||
33 | // GET /comments/:id | 52 | // GET /comments/:id |
34 | router.get("/comments/:id", async (req, res) => { | 53 | router.get("/comments/:id", authenticateToken, async (req, res) => { |
35 | const id = req.params.id; | 54 | const id = req.params.id; |
36 | 55 | ||
37 | const params = { | 56 | const params = { |
@@ -39,34 +58,44 @@ router.get("/comments/:id", async (req, res) => { | |||
39 | }; | 58 | }; |
40 | response = await G.getSubmissionComments(id, params); | 59 | response = await G.getSubmissionComments(id, params); |
41 | 60 | ||
42 | res.render("comments", unescape_submission(response)); | 61 | res.render("comments", { |
62 | data: unescape_submission(response), | ||
63 | user: req.user, | ||
64 | }); | ||
43 | }); | 65 | }); |
44 | 66 | ||
45 | // GET /comments/:parent_id/comment/:child_id | 67 | // GET /comments/:parent_id/comment/:child_id |
46 | router.get("/comments/:parent_id/comment/:child_id", async (req, res) => { | 68 | router.get( |
47 | const parent_id = req.params.parent_id; | 69 | "/comments/:parent_id/comment/:child_id", |
48 | const child_id = req.params.child_id; | 70 | authenticateToken, |
71 | async (req, res) => { | ||
72 | const parent_id = req.params.parent_id; | ||
73 | const child_id = req.params.child_id; | ||
49 | 74 | ||
50 | const params = { | 75 | const params = { |
51 | limit: 50, | 76 | limit: 50, |
52 | }; | 77 | }; |
53 | response = await G.getSingleCommentThread(parent_id, child_id, params); | 78 | response = await G.getSingleCommentThread(parent_id, child_id, params); |
54 | const comments = response.comments; | 79 | const comments = response.comments; |
55 | comments.forEach(unescape_comment); | 80 | comments.forEach(unescape_comment); |
56 | res.render("single_comment_thread", { comments, parent_id }); | 81 | res.render("single_comment_thread", { |
57 | }); | 82 | comments, |
58 | 83 | parent_id, | |
59 | router.get("/login", async (req, res) => { | 84 | user: req.user, |
60 | res.render("login"); | 85 | }); |
61 | }); | 86 | }, |
87 | ); | ||
62 | 88 | ||
63 | // GET /subs | 89 | // GET /subs |
64 | router.get("/subs", async (req, res) => { | 90 | router.get("/subs", authenticateToken, async (req, res) => { |
65 | res.render("subs"); | 91 | const subs = db |
92 | .query("SELECT * FROM subscriptions WHERE user_id = $id") | ||
93 | .all({ id: req.user.id }); | ||
94 | res.render("subs", { subs, user: req.user }); | ||
66 | }); | 95 | }); |
67 | 96 | ||
68 | // GET /media | 97 | // GET /media |
69 | router.get("/media/*", async (req, res) => { | 98 | router.get("/media/*", authenticateToken, async (req, res) => { |
70 | const url = req.params[0]; | 99 | const url = req.params[0]; |
71 | const ext = url.split(".").pop().toLowerCase(); | 100 | const ext = url.split(".").pop().toLowerCase(); |
72 | const kind = ["jpg", "jpeg", "png", "gif", "webp"].includes(ext) | 101 | const kind = ["jpg", "jpeg", "png", "gif", "webp"].includes(ext) |
@@ -81,89 +110,124 @@ router.get("/register", async (req, res) => { | |||
81 | 110 | ||
82 | router.post("/register", async (req, res) => { | 111 | router.post("/register", async (req, res) => { |
83 | const { username, password, confirm_password } = req.body; | 112 | const { username, password, confirm_password } = req.body; |
84 | console.log("Request body:", req.body); | 113 | |
85 | if (!username || !password || !confirm_password) { | 114 | if (!username || !password || !confirm_password) { |
86 | return res.status(400).send("All fields are required"); | 115 | return res.status(400).send("All fields are required"); |
87 | } | 116 | } |
117 | |||
118 | const user = db | ||
119 | .query("SELECT * FROM users WHERE username = $username") | ||
120 | .get({ username }); | ||
121 | if (user) { | ||
122 | return res.render("register", { | ||
123 | message: `user by the name "${username}" exists, choose a different username`, | ||
124 | }); | ||
125 | } | ||
126 | |||
88 | if (password !== confirm_password) { | 127 | if (password !== confirm_password) { |
89 | return res.status(400).send("Passwords do not match"); | 128 | return res.render("register", { |
129 | message: "passwords do not match, try again", | ||
130 | }); | ||
90 | } | 131 | } |
132 | |||
91 | try { | 133 | try { |
92 | const hashedPassword = await hash(password); | 134 | const hashedPassword = await Bun.password.hash(password); |
93 | db.query("INSERT INTO users (username, password_hash) VALUES (?, ?)", [ | 135 | const insertedRecord = db |
94 | username, | 136 | .query( |
95 | hashedPassword, | 137 | "INSERT INTO users (username, password_hash) VALUES ($username, $hashedPassword)", |
96 | ]).run(); | 138 | ) |
97 | res.status(201).redirect("/"); | 139 | .run({ |
140 | username, | ||
141 | hashedPassword, | ||
142 | }); | ||
143 | const id = insertedRecord.lastInsertRowid; | ||
144 | const token = jwt.sign({ username, id }, JWT_KEY, { expiresIn: "100h" }); | ||
145 | res | ||
146 | .status(200) | ||
147 | .cookie("auth_token", token, { | ||
148 | httpOnly: true, | ||
149 | maxAge: 2 * 24 * 60 * 60 * 1000, | ||
150 | }) | ||
151 | .redirect("/"); | ||
98 | } catch (err) { | 152 | } catch (err) { |
99 | console.log(err); | 153 | return res.render("register", { |
100 | res.status(400).send("Error registering user"); | 154 | message: "error registering user, try again later", |
155 | }); | ||
101 | } | 156 | } |
102 | }); | 157 | }); |
103 | 158 | ||
159 | router.get("/login", async (req, res) => { | ||
160 | res.render("login", req.query); | ||
161 | }); | ||
162 | |||
104 | // POST /login | 163 | // POST /login |
105 | router.post("/login", async (req, res) => { | 164 | router.post("/login", async (req, res) => { |
106 | const { username, password } = req.body; | 165 | const { username, password } = req.body; |
107 | const user = db | 166 | const user = db |
108 | .query("SELECT * FROM users WHERE username = ?", [username]) | 167 | .query("SELECT * FROM users WHERE username = $username") |
109 | .get(); | 168 | .get({ username }); |
110 | if (user && await compare(password, user.password_hash)) { | 169 | if (user && (await Bun.password.verify(password, user.password_hash))) { |
111 | res.status(200).redirect("/"); | 170 | const token = jwt.sign({ username, id: user.id }, JWT_KEY, { |
171 | expiresIn: "1h", | ||
172 | }); | ||
173 | res | ||
174 | .cookie("auth_token", token, { | ||
175 | httpOnly: true, | ||
176 | maxAge: 2 * 24 * 60 * 60 * 1000, | ||
177 | }) | ||
178 | .redirect(req.query.redirect || "/"); | ||
112 | } else { | 179 | } else { |
113 | res.status(401).send("Invalid credentials"); | 180 | res.render("login", { |
181 | message: "invalid credentials, try again", | ||
182 | }); | ||
114 | } | 183 | } |
115 | }); | 184 | }); |
116 | 185 | ||
186 | // this would be post, but i cant stuff it in a link | ||
187 | router.get("/logout", (req, res) => { | ||
188 | res.clearCookie("auth_token", { | ||
189 | httpOnly: true, | ||
190 | secure: true, | ||
191 | }); | ||
192 | res.redirect("/login"); | ||
193 | }); | ||
194 | |||
117 | // POST /subscribe | 195 | // POST /subscribe |
118 | router.post("/subscribe", async (req, res) => { | 196 | router.post("/subscribe", authenticateToken, async (req, res) => { |
119 | const { username, subreddit } = req.body; | 197 | const { subreddit } = req.body; |
120 | const user = db | 198 | const user = req.user; |
121 | .query("SELECT * FROM users WHERE username = ?", [username]) | 199 | const existingSubscription = db |
122 | .get(); | 200 | .query( |
123 | if (user) { | 201 | "SELECT * FROM subscriptions WHERE user_id = $id AND subreddit = $subreddit", |
124 | const existingSubscription = db | 202 | ) |
125 | .query( | 203 | .get({ id: user.id, subreddit }); |
126 | "SELECT * FROM subscriptions WHERE user_id = ? AND subreddit = ?", | 204 | if (existingSubscription) { |
127 | [user.id, subreddit], | 205 | res.status(400).send("Already subscribed to this subreddit"); |
128 | ) | ||
129 | .get(); | ||
130 | if (existingSubscription) { | ||
131 | res.status(400).send("Already subscribed to this subreddit"); | ||
132 | } else { | ||
133 | db.query("INSERT INTO subscriptions (user_id, subreddit) VALUES (?, ?)", [ | ||
134 | user.id, | ||
135 | subreddit, | ||
136 | ]).run(); | ||
137 | res.status(201).send("Subscribed successfully"); | ||
138 | } | ||
139 | } else { | 206 | } else { |
140 | res.status(404).send("User not found"); | 207 | db.query( |
208 | "INSERT INTO subscriptions (user_id, subreddit) VALUES ($id, $subreddit)", | ||
209 | ).run({ id: user.id, subreddit }); | ||
210 | res.status(201).send("Subscribed successfully"); | ||
141 | } | 211 | } |
142 | }); | 212 | }); |
143 | 213 | ||
144 | router.post("/unsubscribe", async (req, res) => { | 214 | router.post("/unsubscribe", authenticateToken, async (req, res) => { |
145 | const { username, subreddit } = req.body; | 215 | const { subreddit } = req.body; |
146 | const user = db | 216 | const user = req.user; |
147 | .query("SELECT * FROM users WHERE username = ?", [username]) | 217 | const existingSubscription = db |
148 | .get(); | 218 | .query( |
149 | if (user) { | 219 | "SELECT * FROM subscriptions WHERE user_id = $id AND subreddit = $subreddit", |
150 | const existingSubscription = db | 220 | ) |
151 | .query( | 221 | .get({ id: user.id, subreddit }); |
152 | "SELECT * FROM subscriptions WHERE user_id = ? AND subreddit = ?", | 222 | if (existingSubscription) { |
153 | [user.id, subreddit], | 223 | db.query( |
154 | ) | 224 | "DELETE FROM subscriptions WHERE user_id = $id AND subreddit = $subreddit", |
155 | .get(); | 225 | ).run({ id: user.id, subreddit }); |
156 | if (existingSubscription) { | 226 | console.log("done"); |
157 | db.run("DELETE FROM subscriptions WHERE user_id = ? AND subreddit = ?", [ | 227 | res.status(200).send("Unsubscribed successfully"); |
158 | user.id, | ||
159 | subreddit, | ||
160 | ]); | ||
161 | res.status(200).send("Unsubscribed successfully"); | ||
162 | } else { | ||
163 | res.status(400).send("Subscription not found"); | ||
164 | } | ||
165 | } else { | 228 | } else { |
166 | res.status(404).send("User not found"); | 229 | console.log("not"); |
230 | res.status(400).send("Subscription not found"); | ||
167 | } | 231 | } |
168 | }); | 232 | }); |
169 | 233 | ||