From c923493108d7dbb7e2cb3703f0c50814803eb634 Mon Sep 17 00:00:00 2001 From: counterweight Date: Wed, 5 Mar 2025 16:04:44 +0100 Subject: [PATCH] start api routes --- src/app.js | 7 +- src/dependencies.js | 4 + src/routes/apiRoutes.js | 552 +++++++++++++++++++++------------------- 3 files changed, 290 insertions(+), 273 deletions(-) diff --git a/src/app.js b/src/app.js index 0745caa..dc3cf83 100644 --- a/src/app.js +++ b/src/app.js @@ -18,11 +18,8 @@ function createApp(dependencies) { app.use(dependencies.middlewares.createSessionMiddleware); - const webRoutes = dependencies.webRoutes; - const apiRoutes = require('./routes/apiRoutes'); - - app.use('/', webRoutes); - app.use('/api', apiRoutes); + app.use('/', dependencies.webRoutes); + app.use('/api', dependencies.apiRoutes); app.use(express.static(path.join(__dirname, 'public'))); diff --git a/src/dependencies.js b/src/dependencies.js index 13a1af7..4e44210 100644 --- a/src/dependencies.js +++ b/src/dependencies.js @@ -15,6 +15,10 @@ function buildDependencies() { invitesService, }); dependencies.webRoutes = webRoutesProvider.provide(); + + const ApiRoutesProvider = require('./routes/apiRoutes'); + const apiRoutesProvider = new ApiRoutesProvider(); + dependencies.apiRoutes = apiRoutesProvider.provide(); return dependencies; } diff --git a/src/routes/apiRoutes.js b/src/routes/apiRoutes.js index 9d5516c..f3a0bdc 100644 --- a/src/routes/apiRoutes.js +++ b/src/routes/apiRoutes.js @@ -16,282 +16,298 @@ const profileService = profileServiceProvider(ContactDetailsSet, NymSet); const router = express.Router(); -router.get('/signup/nostr-challenge', async (req, res) => { - const inviteUuid = req.cookies.inviteUuid; +class ApiRoutesProvider { + constructor() {} - 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.', - }); - } + provide() { + router.get('/signup/nostr-challenge', async (req, res) => { + const inviteUuid = req.cookies.inviteUuid; - if (error instanceof errors.AlreadyUsedError) { - return res.status(410).json({ - success: false, - message: 'That invite has already been used.', - }); - } + 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.', + }); + } - return res.status(500).json({ - success: false, - message: 'Unexpected error.', - }); - } + if (error instanceof errors.AlreadyUsedError) { + return res.status(410).json({ + success: false, + message: 'That invite has already been used.', + }); + } - let relatedNostrChallenge; - try { - relatedNostrChallenge = await nostrService.getNostrChallenge( - signUpChallenge.nostr_challenge_uuid - ); - } catch (error) { - return res.status(500).json({ - success: false, - message: `Unexpected error: ${error}`, - }); - } - - return res.status(200).json({ challenge: relatedNostrChallenge.challenge }); -}); - -router.post('/signup/nostr-verify', async (req, res) => { - const signedEvent = req.body; - const sessionUuid = req.cookies.sessionUuid; - - let completedSignUpChallenge; - try { - completedSignUpChallenge = - await invitesService.verifySignUpChallenge(signedEvent); - } catch (error) { - if (error instanceof errors.ExpiredError) { - return res.status(410).json({ - success: false, - message: 'The challenge has expired, request a new one.', - }); - } - if (error instanceof errors.AlreadyUsedError) { - return res.status(410).json({ - success: false, - message: 'The challenge has been used, request a new one.', - }); - } - if (error instanceof errors.InvalidSignatureError) { - return res.status(400).json({ - success: false, - message: 'The challenge signature is not valid.', - }); - } - } - - await sessionService.relateSessionToPublicKey( - sessionUuid, - completedSignUpChallenge.public_key - ); - - return res.status(200).json({ success: true }); -}); - -router.get('/login/nostr-challenge', async (req, res) => { - let loginChallenge; - try { - loginChallenge = await loginService.createLoginChallenge(); - } catch (error) { - return res.status(500).json({ - success: false, - message: 'Unexpected error.', - }); - } - - let relatedNostrChallenge; - try { - relatedNostrChallenge = await nostrService.getNostrChallenge( - loginChallenge.nostr_challenge_uuid - ); - } catch (error) { - return res.status(500).json({ - success: false, - message: `Unexpected error: ${error}`, - }); - } - - return res.status(200).json({ challenge: relatedNostrChallenge.challenge }); -}); - -router.post('/login/nostr-verify', async (req, res) => { - const signedEvent = req.body; - const sessionUuid = req.cookies.sessionUuid; - - let completedLoginChallenge; - try { - completedLoginChallenge = - await loginService.verifyLoginChallenge(signedEvent); - } catch (error) { - console.log('helo5'); - console.log(error); - if (error instanceof errors.ExpiredError) { - return res.status(410).json({ - success: false, - message: 'The challenge has expired, request a new one.', - }); - } - if (error instanceof errors.AlreadyUsedError) { - return res.status(410).json({ - success: false, - message: 'The challenge has been used, request a new one.', - }); - } - if (error instanceof errors.InvalidSignatureError) { - return res.status(400).json({ - success: false, - message: 'The challenge signature is not valid.', - }); - } - if (error instanceof errors.ForbiddenError) { - console.log('helo?1'); - return res.status(403).json({ - success: false, - message: 'This public key is not authorized.', - }); - } - - return res.status(500).json({ - success: false, - message: 'Unexpected error.', - }); - } - console.log('helo?2'); - console.log(completedLoginChallenge); - await sessionService.relateSessionToPublicKey( - sessionUuid, - completedLoginChallenge.public_key - ); - - return res.status(200).json({ success: true }); -}); - -router.post( - '/set-contact-details', - rejectIfNotAuthorizedMiddleware, - attachPublicKeyMiddleware, - async (req, res) => { - const encryptedContactDetails = req.body.encryptedContactDetails; - const publicKey = req.cookies.publicKey; - - if (!encryptedContactDetails) { - return res.status(400).json({ - success: false, - message: 'Missing contact details.', - }); - } - - await profileService.setContactDetails(publicKey, encryptedContactDetails); - - return res.status(200).json({ - success: true, - message: 'Contact details set successfully.', - }); - } -); - -router.post( - '/set-nym', - rejectIfNotAuthorizedMiddleware, - attachPublicKeyMiddleware, - async (req, res) => { - const nym = req.body.nym; - const publicKey = req.cookies.publicKey; - - if (!nym) { - return res.status(400).json({ - success: false, - message: 'Missing nym', - }); - } - - await profileService.setNym(publicKey, nym); - - return res.status(200).json({ - success: true, - message: 'Nym set successfully.', - }); - } -); - -router.post( - '/offer', - rejectIfNotAuthorizedMiddleware, - attachPublicKeyMiddleware, - async (req, res) => { - const publicKey = req.cookies.publicKey; - const offerDetails = req.body.offerDetails; - - await offerService.createOffer(publicKey, offerDetails); - - return res.status(200).json({ - success: true, - message: 'Offer created successfully', - }); - } -); - -router.delete( - '/offer/:offerUuid', - rejectIfNotAuthorizedMiddleware, - attachPublicKeyMiddleware, - async (req, res) => { - const offerUuid = req.params.offerUuid; - - try { - await offerService.deleteOffer(offerUuid); - } catch (error) { - if (error instanceof errors.NotFoundError) { - return res.status(404).json({ + return res.status(500).json({ success: false, - message: 'Offer not found for the given public key.', + message: 'Unexpected error.', }); } - return res.status(500).json({ - success: false, - message: 'Unexpected error.', - }); - } - return res.status(204).json({ - success: true, - message: 'Offer deleted successfully', + let relatedNostrChallenge; + try { + relatedNostrChallenge = await nostrService.getNostrChallenge( + signUpChallenge.nostr_challenge_uuid + ); + } catch (error) { + return res.status(500).json({ + success: false, + message: `Unexpected error: ${error}`, + }); + } + + return res + .status(200) + .json({ challenge: relatedNostrChallenge.challenge }); }); + + router.post('/signup/nostr-verify', async (req, res) => { + const signedEvent = req.body; + const sessionUuid = req.cookies.sessionUuid; + + let completedSignUpChallenge; + try { + completedSignUpChallenge = + await invitesService.verifySignUpChallenge(signedEvent); + } catch (error) { + if (error instanceof errors.ExpiredError) { + return res.status(410).json({ + success: false, + message: 'The challenge has expired, request a new one.', + }); + } + if (error instanceof errors.AlreadyUsedError) { + return res.status(410).json({ + success: false, + message: 'The challenge has been used, request a new one.', + }); + } + if (error instanceof errors.InvalidSignatureError) { + return res.status(400).json({ + success: false, + message: 'The challenge signature is not valid.', + }); + } + } + + await sessionService.relateSessionToPublicKey( + sessionUuid, + completedSignUpChallenge.public_key + ); + + return res.status(200).json({ success: true }); + }); + + router.get('/login/nostr-challenge', async (req, res) => { + let loginChallenge; + try { + loginChallenge = await loginService.createLoginChallenge(); + } catch (error) { + return res.status(500).json({ + success: false, + message: 'Unexpected error.', + }); + } + + let relatedNostrChallenge; + try { + relatedNostrChallenge = await nostrService.getNostrChallenge( + loginChallenge.nostr_challenge_uuid + ); + } catch (error) { + return res.status(500).json({ + success: false, + message: `Unexpected error: ${error}`, + }); + } + + return res + .status(200) + .json({ challenge: relatedNostrChallenge.challenge }); + }); + + router.post('/login/nostr-verify', async (req, res) => { + const signedEvent = req.body; + const sessionUuid = req.cookies.sessionUuid; + + let completedLoginChallenge; + try { + completedLoginChallenge = + await loginService.verifyLoginChallenge(signedEvent); + } catch (error) { + console.log('helo5'); + console.log(error); + if (error instanceof errors.ExpiredError) { + return res.status(410).json({ + success: false, + message: 'The challenge has expired, request a new one.', + }); + } + if (error instanceof errors.AlreadyUsedError) { + return res.status(410).json({ + success: false, + message: 'The challenge has been used, request a new one.', + }); + } + if (error instanceof errors.InvalidSignatureError) { + return res.status(400).json({ + success: false, + message: 'The challenge signature is not valid.', + }); + } + if (error instanceof errors.ForbiddenError) { + console.log('helo?1'); + return res.status(403).json({ + success: false, + message: 'This public key is not authorized.', + }); + } + + return res.status(500).json({ + success: false, + message: 'Unexpected error.', + }); + } + console.log('helo?2'); + console.log(completedLoginChallenge); + await sessionService.relateSessionToPublicKey( + sessionUuid, + completedLoginChallenge.public_key + ); + + return res.status(200).json({ success: true }); + }); + + router.post( + '/set-contact-details', + rejectIfNotAuthorizedMiddleware, + attachPublicKeyMiddleware, + async (req, res) => { + const encryptedContactDetails = req.body.encryptedContactDetails; + const publicKey = req.cookies.publicKey; + + if (!encryptedContactDetails) { + return res.status(400).json({ + success: false, + message: 'Missing contact details.', + }); + } + + await profileService.setContactDetails( + publicKey, + encryptedContactDetails + ); + + return res.status(200).json({ + success: true, + message: 'Contact details set successfully.', + }); + } + ); + + router.post( + '/set-nym', + rejectIfNotAuthorizedMiddleware, + attachPublicKeyMiddleware, + async (req, res) => { + const nym = req.body.nym; + const publicKey = req.cookies.publicKey; + + if (!nym) { + return res.status(400).json({ + success: false, + message: 'Missing nym', + }); + } + + await profileService.setNym(publicKey, nym); + + return res.status(200).json({ + success: true, + message: 'Nym set successfully.', + }); + } + ); + + router.post( + '/offer', + rejectIfNotAuthorizedMiddleware, + attachPublicKeyMiddleware, + async (req, res) => { + const publicKey = req.cookies.publicKey; + const offerDetails = req.body.offerDetails; + + await offerService.createOffer(publicKey, offerDetails); + + return res.status(200).json({ + success: true, + message: 'Offer created successfully', + }); + } + ); + + router.delete( + '/offer/:offerUuid', + rejectIfNotAuthorizedMiddleware, + attachPublicKeyMiddleware, + async (req, res) => { + const offerUuid = req.params.offerUuid; + + try { + await offerService.deleteOffer(offerUuid); + } catch (error) { + if (error instanceof errors.NotFoundError) { + return res.status(404).json({ + success: false, + message: 'Offer not found for the given public key.', + }); + } + return res.status(500).json({ + success: false, + message: 'Unexpected error.', + }); + } + + return res.status(204).json({ + success: true, + message: 'Offer deleted successfully', + }); + } + ); + + router.get( + '/publickey-offers', + rejectIfNotAuthorizedMiddleware, + attachPublicKeyMiddleware, + async (req, res) => { + console.log('elo'); + const publicKey = req.cookies.publicKey; + + const offers = await offerService.getOffersByPublicKey(publicKey); + + if (!offers) { + return res.status(404).json({ + success: true, + message: 'No offers posted by this public key.', + }); + } + + if (offers) { + return res.status(200).json({ + success: true, + message: 'Offers found', + data: offers, + }); + } + } + ); + + return router; } -); +} -router.get( - '/publickey-offers', - rejectIfNotAuthorizedMiddleware, - attachPublicKeyMiddleware, - async (req, res) => { - console.log('elo'); - const publicKey = req.cookies.publicKey; - - const offers = await offerService.getOffersByPublicKey(publicKey); - - if (!offers) { - return res.status(404).json({ - success: true, - message: 'No offers posted by this public key.', - }); - } - - if (offers) { - return res.status(200).json({ - success: true, - message: 'Offers found', - data: offers, - }); - } - } -); - -module.exports = router; +module.exports = ApiRoutesProvider;