diff options
author | Akshay <[email protected]> | 2024-11-15 20:14:41 +0000 |
---|---|---|
committer | Akshay <[email protected]> | 2024-11-15 20:14:41 +0000 |
commit | d4a83cb44dc98fe78f9061408137a43049344b1d (patch) | |
tree | d4314ce0b793150f6984a8f47f36f9695f3c0747 /src | |
parent | e2c410822ad8aea8ec702cef6bba5de352b8c73d (diff) |
add invite system
Diffstat (limited to 'src')
-rw-r--r-- | src/invite.js | 37 | ||||
-rw-r--r-- | src/public/styles.css | 7 | ||||
-rw-r--r-- | src/routes/index.js | 13 | ||||
-rw-r--r-- | src/views/register.pug | 8 |
4 files changed, 60 insertions, 5 deletions
diff --git a/src/invite.js b/src/invite.js new file mode 100644 index 0000000..0f6624c --- /dev/null +++ b/src/invite.js | |||
@@ -0,0 +1,37 @@ | |||
1 | const { db } = require("./db"); | ||
2 | |||
3 | const validateInviteToken = async (req, res, next) => { | ||
4 | const token = req.query.token; | ||
5 | |||
6 | if (!token) { | ||
7 | return res.render("register", { | ||
8 | message: "this instance requires an invite", | ||
9 | isDisabled: true, | ||
10 | }); | ||
11 | } | ||
12 | |||
13 | const invite = db | ||
14 | .query("SELECT * FROM invites WHERE token = $token AND usedAt IS null") | ||
15 | .get({ token }); | ||
16 | |||
17 | if (!invite) { | ||
18 | return res.render("register", { | ||
19 | message: "this invite token is invalid", | ||
20 | isDisabled: true, | ||
21 | }); | ||
22 | } | ||
23 | |||
24 | if (invite.usedAt) { | ||
25 | return res.render("register", { | ||
26 | message: "this invite has been claimed", | ||
27 | isDisabled: true, | ||
28 | }); | ||
29 | } | ||
30 | |||
31 | req.invite = invite; | ||
32 | next(); | ||
33 | }; | ||
34 | |||
35 | module.exports = { | ||
36 | validateInviteToken, | ||
37 | }; | ||
diff --git a/src/public/styles.css b/src/public/styles.css index 0a0a2e2..523e81b 100644 --- a/src/public/styles.css +++ b/src/public/styles.css | |||
@@ -491,6 +491,13 @@ form input[type="submit"]:hover { | |||
491 | color: var(--bg-color); | 491 | color: var(--bg-color); |
492 | } | 492 | } |
493 | 493 | ||
494 | .submit-button button:disabled { | ||
495 | width: 100%; | ||
496 | padding: 12px; | ||
497 | background-color: var(--bg-color-muted); | ||
498 | color: var(--text-color-muted); | ||
499 | } | ||
500 | |||
494 | .register-error-message { | 501 | .register-error-message { |
495 | flex-flow: row wrap; | 502 | flex-flow: row wrap; |
496 | color: var(--error-text-color); | 503 | color: var(--error-text-color); |
diff --git a/src/routes/index.js b/src/routes/index.js index 1141009..8529595 100644 --- a/src/routes/index.js +++ b/src/routes/index.js | |||
@@ -6,6 +6,7 @@ const geddit = require("../geddit.js"); | |||
6 | const { JWT_KEY } = require("../"); | 6 | const { JWT_KEY } = require("../"); |
7 | const { db } = require("../db"); | 7 | const { db } = require("../db"); |
8 | const { authenticateToken } = require("../auth"); | 8 | const { authenticateToken } = require("../auth"); |
9 | const { validateInviteToken } = require("../invite"); | ||
9 | 10 | ||
10 | const router = express.Router(); | 11 | const router = express.Router(); |
11 | const G = new geddit.Geddit(); | 12 | const G = new geddit.Geddit(); |
@@ -113,11 +114,11 @@ router.get("/media/*", authenticateToken, async (req, res) => { | |||
113 | res.render("media", { kind, url }); | 114 | res.render("media", { kind, url }); |
114 | }); | 115 | }); |
115 | 116 | ||
116 | router.get("/register", async (req, res) => { | 117 | router.get("/register", validateInviteToken, async (req, res) => { |
117 | res.render("register"); | 118 | res.render("register", { isDisabled: false, token: req.query.token }); |
118 | }); | 119 | }); |
119 | 120 | ||
120 | router.post("/register", async (req, res) => { | 121 | router.post("/register", validateInviteToken, async (req, res) => { |
121 | const { username, password, confirm_password } = req.body; | 122 | const { username, password, confirm_password } = req.body; |
122 | 123 | ||
123 | if (!username || !password || !confirm_password) { | 124 | if (!username || !password || !confirm_password) { |
@@ -141,6 +142,11 @@ router.post("/register", async (req, res) => { | |||
141 | 142 | ||
142 | try { | 143 | try { |
143 | const hashedPassword = await Bun.password.hash(password); | 144 | const hashedPassword = await Bun.password.hash(password); |
145 | |||
146 | db.query("UPDATE invites SET usedAt = CURRENT_TIMESTAMP WHERE id = $id", { | ||
147 | id: req.invite.id, | ||
148 | }); | ||
149 | |||
144 | const insertedRecord = db | 150 | const insertedRecord = db |
145 | .query( | 151 | .query( |
146 | "INSERT INTO users (username, password_hash) VALUES ($username, $hashedPassword)", | 152 | "INSERT INTO users (username, password_hash) VALUES ($username, $hashedPassword)", |
@@ -159,6 +165,7 @@ router.post("/register", async (req, res) => { | |||
159 | }) | 165 | }) |
160 | .redirect("/"); | 166 | .redirect("/"); |
161 | } catch (err) { | 167 | } catch (err) { |
168 | console.log(err); | ||
162 | return res.render("register", { | 169 | return res.render("register", { |
163 | message: "error registering user, try again later", | 170 | message: "error registering user, try again later", |
164 | }); | 171 | }); |
diff --git a/src/views/register.pug b/src/views/register.pug index 22bca48..bb43a72 100644 --- a/src/views/register.pug +++ b/src/views/register.pug | |||
@@ -1,5 +1,6 @@ | |||
1 | include ../mixins/head | 1 | include ../mixins/head |
2 | 2 | ||
3 | - var action = "/register" + (token?`?token=${token}`:'') | ||
3 | doctype html | 4 | doctype html |
4 | html | 5 | html |
5 | +head("register") | 6 | +head("register") |
@@ -9,7 +10,7 @@ html | |||
9 | if message | 10 | if message |
10 | div.register-error-message | 11 | div.register-error-message |
11 | | #{message} | 12 | | #{message} |
12 | form(action="/register" method="post") | 13 | form(action=`${action}` method="post") |
13 | div.input-text | 14 | div.input-text |
14 | label(for="username") username | 15 | label(for="username") username |
15 | input(type="text" name="username" required) | 16 | input(type="text" name="username" required) |
@@ -20,7 +21,10 @@ html | |||
20 | label(for="confirm_password") confirm password | 21 | label(for="confirm_password") confirm password |
21 | input(type="password" name="confirm_password" required) | 22 | input(type="password" name="confirm_password" required) |
22 | div.submit-button | 23 | div.submit-button |
23 | button(type="submit") register | 24 | if isDisabled |
25 | button(type="submit" disabled) register'nt :( | ||
26 | else | ||
27 | button(type="submit") register | ||
24 | div | 28 | div |
25 | p | 29 | p |
26 | | already have an account? | 30 | | already have an account? |