diff --git a/src/errors.js b/src/errors.js index 3c6cd27..023ba59 100644 --- a/src/errors.js +++ b/src/errors.js @@ -5,6 +5,13 @@ class ChallengedUsedError extends Error { } } +class AlreadyUsedError extends Error { + constructor(message) { + super(message); + this.name = "AlreadyUsedError" + } +} + class InvalidSignatureError extends Error { constructor(message) { super(message); @@ -27,8 +34,7 @@ class NotFoundError extends Error { } module.exports = { - ChallengedUsedError, + AlreadyUsedError, InvalidSignatureError, - AppInvitedUsedError, NotFoundError }; \ No newline at end of file diff --git a/src/public/javascript/invite.js b/src/public/javascript/invite.js index 1521ccf..89e9b09 100644 --- a/src/public/javascript/invite.js +++ b/src/public/javascript/invite.js @@ -10,40 +10,51 @@ window.onload = function () { async function acceptInvite() { - if (!window.nostr) { - console.log("No Nostr extension found."); - return { success: false, error: "No Nostr extension detected." }; + let challengeResponse; + try { + challengeResponse = await fetch('/api/signup/nostr-challenge', { + method: 'GET', + headers: { + 'Content-Type': 'application/json' + } + }); + } catch (error) { + console.log(`Something went wrong: ${error}`); + return; } + const { challenge } = await challengeResponse.json(); + let pubkey; try { - const challengeResponse = await fetch("/api/signup/nostr-challenge"); - if (!challengeResponse.ok) throw new Error("Failed to fetch challenge"); - const { challenge } = await challengeResponse.json(); + pubkey = await window.nostr.getPublicKey(); + } catch (error) { + document.querySelector('#rejected-nostr-nudges').style.display = 'block'; + return; + } + const event = { + kind: 22242, + created_at: Math.floor(Date.now() / 1000), + tags: [["challenge", challenge]], + content: "Sign this challenge to authenticate", + pubkey: pubkey + }; - const pubkey = await window.nostr.getPublicKey(); + let signedEvent; + try { + signedEvent = await window.nostr.signEvent(event); + } catch (error) { + document.querySelector('#rejected-nostr-nudges').style.display = 'block'; + return; + } - const event = { - kind: 22242, - created_at: Math.floor(Date.now() / 1000), - tags: [["challenge", challenge]], - content: "Sign this challenge to authenticate", - pubkey: pubkey - }; + const verifyResponse = await fetch("/api/signup/nostr-verify", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify(signedEvent), + }); - const signedEvent = await window.nostr.signEvent(event); + if (verifyResponse.status === 200) { - const verifyResponse = await fetch("/api/signup/nostr-verify", { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify(signedEvent), - }); - - if (verifyResponse.status === 200) { - - } - - - - } catch (error) { } + } } \ No newline at end of file diff --git a/src/routes/apiRoutes.js b/src/routes/apiRoutes.js index cf0943d..384de44 100644 --- a/src/routes/apiRoutes.js +++ b/src/routes/apiRoutes.js @@ -1,5 +1,4 @@ const express = require('express'); -const crypto = require("crypto"); const invitesService = require('../services/invitesService'); const nostrService = require('../services/nostrService'); @@ -9,17 +8,48 @@ const errors = require('../errors'); const router = express.Router(); router.get('/signup/nostr-challenge', async (req, res) => { + console.log("I'm heeeere") const inviteUuid = req.cookies.inviteUuid; - const signUpChallenge = await invitesService.createSignUpChallenge( - inviteUuid - ) + let signUpChallenge; + try { + signUpChallenge = await invitesService.createSignUpChallenge( + inviteUuid + ) + } catch (error) { + if (error instanceof errors.NotFoundError) { + return res.status(404).json({ + success: false, + message: 'Could not find invite with that id.' + }) + } - const relatedNostrChallenge = await nostrService.getNostrChallenge( - signUpChallenge.nostr_challenge_uuid - ) + if (error instanceof errors.AlreadyUsedError) { + return res.status(410).json({ + success: false, + message: 'That invite has already been used.' + }) + } - res.status(200).json({ 'challenge': relatedNostrChallenge.challenge }); + return res.status(500).json({ + success: false, + message: 'Unexpected error.' + }) + } + + let relatedNostrChallenge; + try { + relatedNostrChallenge = await nostrService.getNostrChallenge( + signUpChallenge.nostr_challenge_uuid + ) + } catch (error) { + return res.status(500).json({ + success: false, + message: 'Unexpected error.' + }) + } + + return res.status(200).json({ 'challenge': relatedNostrChallenge.challenge }); }); @@ -34,7 +64,7 @@ router.post("/signup/nostr-verify", async (req, res) => { if (error instanceof TimeoutError) { console.error('The challenge is outdated.'); } - if (error instanceof errors.ChallengedUsedError) { + if (error instanceof errors.AlreadyUsedError) { console.error('The challenge was already used, request a new one.'); } if (error instanceof errors.InvalidSignatureError) { diff --git a/src/routes/webRoutes.js b/src/routes/webRoutes.js index d8c0c57..fbff9d6 100644 --- a/src/routes/webRoutes.js +++ b/src/routes/webRoutes.js @@ -13,24 +13,23 @@ router.get('/invite/:inviteUuid', async (req, res) => { res.cookie('inviteUuid', inviteUuid, { httpOnly: true, maxAge: 86400000 }); + let invite; try { - - if (await !invitesService.appInviteExists(inviteUuid)) { - return res.status(404).render('error', { message: 'Invite not found' }); + invite = await invitesService.getAppInvite(inviteUuid); + if (!invite) { + return res.status(404).render('error', { message: 'Invite not found.' }); } - const invite = await invitesService.getAppInvite(inviteUuid); - if (await invitesService.isAppInviteSpent(inviteUuid)) { - return res.render('invite_spent', { invite }) + return res.status(410).render('invite_spent', { invite }) } - return res.render('invite', { invite }); - } catch (error) { console.error('Error fetching invite:', error); return res.status(500).render('error', { message: 'An error occurred' }); } + + return res.render('invite', { invite }); }); router.get('/private', authMiddleware, (req, res) => { diff --git a/src/services/invitesService.js b/src/services/invitesService.js index 28258f2..1bacbd5 100644 --- a/src/services/invitesService.js +++ b/src/services/invitesService.js @@ -49,7 +49,7 @@ async function createSignUpChallenge(appInviteUuid) { } if (await isAppInviteSpent(appInviteUuid)) { - throw new errors.AppInvitedUsedError("Invite has already been used.") + throw new errors.AlreadyUsedError("Invite has already been used.") } const nostrChallenge = await nostrService.createNostrChallenge() @@ -84,7 +84,7 @@ async function verifySignUpChallenge(signedEvent) { console.log(`Found this signup challenge: ${signUpChallenge}`); if (await nostrService.hasNostrChallengeBeenCompleted(challenge)) { - throw new errors.ChallengedUsedError("This challenge has already been used."); + throw new errors.AlreadyUsedError("This challenge has already been used."); } console.log(`I'm gonna verify the nostr challenge`); const completedNostrChallenge = await nostrService.verifyNostrChallenge(signedEvent); diff --git a/src/services/nostrService.js b/src/services/nostrService.js index e970e54..8a752d9 100644 --- a/src/services/nostrService.js +++ b/src/services/nostrService.js @@ -58,7 +58,7 @@ async function verifyNostrChallenge(signedEvent) { console.log("Checking if completed") if (await hasNostrChallengeBeenCompleted(challenge)) { - throw new errors.ChallengedUsedError("Challenge already used, request new one."); + throw new errors.AlreadyUsedError("Challenge already used, request new one."); } console.log("Checking if valid") diff --git a/src/views/invite.ejs b/src/views/invite.ejs index 1bfdd4d..a44c898 100644 --- a/src/views/invite.ejs +++ b/src/views/invite.ejs @@ -17,6 +17,9 @@
+