diff --git a/src/middlewares/attachPublicKeyMiddleware.js b/src/middlewares/attachPublicKeyMiddleware.js new file mode 100644 index 0000000..23d4877 --- /dev/null +++ b/src/middlewares/attachPublicKeyMiddleware.js @@ -0,0 +1,13 @@ +const sessionService = require('../services/sessionService'); + +async function attachPublicKeyMiddleware(req, res, next) { + + const publicKey = await sessionService.getPublicKeyRelatedToSession( + req.cookies.sessionUuid + ) + req.cookies.publicKey = publicKey; + + next(); +} + +module.exports = attachPublicKeyMiddleware; diff --git a/src/middlewares/rejectIfNotAuthorizedMiddleware.js b/src/middlewares/rejectIfNotAuthorizedMiddleware.js new file mode 100644 index 0000000..cd70f54 --- /dev/null +++ b/src/middlewares/rejectIfNotAuthorizedMiddleware.js @@ -0,0 +1,13 @@ +const sessionService = require('../services/sessionService'); + +async function rejectIfNotAuthorizedMiddleware(req, res, next) { + if (!(await sessionService.isSessionAuthorized(req.cookies.sessionUuid))) { + return res.status(403).json({ + success: false, + message: 'Your session is not authorized.' + }) + } + next(); +} + +module.exports = rejectIfNotAuthorizedMiddleware; diff --git a/src/middlewares/sessionMiddleware.js b/src/middlewares/sessionMiddleware.js index a6813a6..3a68880 100644 --- a/src/middlewares/sessionMiddleware.js +++ b/src/middlewares/sessionMiddleware.js @@ -13,25 +13,19 @@ async function createSessionMiddleware(req, res, next) { const sessionUuid = req.cookies.sessionUuid; - console.log("Running cookie middleware") - if (!sessionUuid) { - console.log("Found no cookie") const newSession = await setAndPersistNewSession(res); req.cookies.sessionUuid = newSession.uuid; } if (sessionUuid) { - console.log(`Found a cookie ${sessionUuid}`) if (!(await sessionService.isSessionValid(sessionUuid))) { - console.log("But it's not valid") const newSession = await setAndPersistNewSession(res); req.cookies.sessionUuid = newSession.uuid; } } - console.log("Moving on...") next(); } diff --git a/src/models/ContactDetailsSet.js b/src/models/ContactDetailsSet.js new file mode 100644 index 0000000..0e6e635 --- /dev/null +++ b/src/models/ContactDetailsSet.js @@ -0,0 +1,27 @@ +const { DataTypes } = require('sequelize'); +const sequelize = require('../database'); + +const ContactDetailsSet = sequelize.define('ContactDetailsSet', { + uuid: { + type: DataTypes.UUID, + allowNull: false, + unique: true, + primaryKey: true + }, + public_key: { + type: DataTypes.STRING, + allowNull: false + }, + encrypted_contact_details: { + type: DataTypes.TEXT, + allowNull: false + }, + created_at: { + type: DataTypes.DATE, + allowNull: false + } +}, { + tableName: 'contact_details_set' +}); + +module.exports = ContactDetailsSet; \ No newline at end of file diff --git a/src/public/javascript/createProfile.js b/src/public/javascript/createProfile.js index 717cbb8..7292f3d 100644 --- a/src/public/javascript/createProfile.js +++ b/src/public/javascript/createProfile.js @@ -45,6 +45,12 @@ class ContactDetails { return fragment; } + + async getEncryptedContactDetails() { + const jsonString = JSON.stringify(this.details); + const encryptedContactDetails = await window.nostr.nip04.encrypt(await window.nostr.getPublicKey(), jsonString); + return encryptedContactDetails; + } } let contactDetails; @@ -67,4 +73,21 @@ window.onload = () => { input.value = ''; }); }); + + document + .querySelector('#submit-details-button') + .addEventListener( + 'click', + async () => { + const encryptedContactDetails = await contactDetails.getEncryptedContactDetails(); + await fetch('/api/set-contact-details', + { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ encryptedContactDetails }) + }); + } + ); }; \ No newline at end of file diff --git a/src/routes/apiRoutes.js b/src/routes/apiRoutes.js index 4d1afc7..b7f3fc6 100644 --- a/src/routes/apiRoutes.js +++ b/src/routes/apiRoutes.js @@ -3,12 +3,14 @@ const express = require('express'); const invitesService = require('../services/invitesService'); const nostrService = require('../services/nostrService'); const sessionService = require('../services/sessionService'); +const profileService = require('../services/profileService'); const errors = require('../errors'); +const attachPublicKeyMiddleware = require('../middlewares/attachPublicKeyMiddleware'); +const rejectIfNotAuthorizedMiddleware = require('../middlewares/rejectIfNotAuthorizedMiddleware'); const router = express.Router(); router.get('/signup/nostr-challenge', async (req, res) => { - console.log("I'm heeeere") const inviteUuid = req.cookies.inviteUuid; let signUpChallenge; @@ -89,4 +91,30 @@ router.post("/signup/nostr-verify", async (req, res) => { 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.' + }) + }) + module.exports = router; diff --git a/src/services/nostrService.js b/src/services/nostrService.js index 8a752d9..e0e5542 100644 --- a/src/services/nostrService.js +++ b/src/services/nostrService.js @@ -51,23 +51,19 @@ async function verifyNostrChallenge(signedEvent) { const challengeTag = signedEvent.tags.find(tag => tag[0] === "challenge"); const challenge = challengeTag[1]; - console.log("Checking if fresh") if (!(await isNostrChallengeFresh(challenge))) { throw TimeoutError("Challenge expired, request new one."); } - console.log("Checking if completed") if (await hasNostrChallengeBeenCompleted(challenge)) { throw new errors.AlreadyUsedError("Challenge already used, request new one."); } - console.log("Checking if valid") const isSignatureValid = verifyEvent(signedEvent); if (!isSignatureValid) { throw new errors.InvalidSignatureError("Signature is not valid."); } - console.log("Persisting") return await NostrChallengeCompleted.create({ 'uuid': uuid.v7(), challenge: challenge, diff --git a/src/services/profileService.js b/src/services/profileService.js new file mode 100644 index 0000000..f550bc4 --- /dev/null +++ b/src/services/profileService.js @@ -0,0 +1,17 @@ +const uuid = require('uuid'); +const ContactDetailsSet = require('../models/ContactDetailsSet'); + +async function setContactDetails(publicKey, encryptedContactDetails) { + return ContactDetailsSet.create( + { + 'uuid': uuid.v7(), + public_key: publicKey, + encrypted_contact_details: encryptedContactDetails, + created_at: new Date().toISOString() + } + ) +} + +module.exports = { + setContactDetails +}; \ No newline at end of file diff --git a/src/services/sessionService.js b/src/services/sessionService.js index 4542630..0aaa0d9 100644 --- a/src/services/sessionService.js +++ b/src/services/sessionService.js @@ -4,7 +4,6 @@ const SessionCreated = require('../models/SessionCreated'); const SessionRelatedToPublickey = require('../models/SessionRelatedToPublickey'); const invitesService = require('./invitesService'); - const constants = require('../constants'); async function createSession(sessionUuid) { @@ -71,9 +70,23 @@ async function isSessionAuthorized(sessionUuid) { return false; } +async function getPublicKeyRelatedToSession(sessionUuid) { + const sessionRelatedToPublickey = await SessionRelatedToPublickey.findOne( + { + where: { + session_uuid: sessionUuid + } + } + ); + + return sessionRelatedToPublickey.public_key; + +} + module.exports = { createSession, isSessionValid, relateSessionToPublicKey, - isSessionAuthorized + isSessionAuthorized, + getPublicKeyRelatedToSession } \ No newline at end of file diff --git a/src/views/createProfile.ejs b/src/views/createProfile.ejs index d491ae9..809b7fd 100644 --- a/src/views/createProfile.ejs +++ b/src/views/createProfile.ejs @@ -17,8 +17,6 @@