storing contact details works

This commit is contained in:
counterweight 2025-02-14 01:32:03 +01:00
parent 00fc6bb258
commit 6b52d06b3e
Signed by: counterweight
GPG key ID: 883EDBAA726BD96C
10 changed files with 138 additions and 15 deletions

View file

@ -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;

View file

@ -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;

View file

@ -13,25 +13,19 @@ async function createSessionMiddleware(req, res, next) {
const sessionUuid = req.cookies.sessionUuid; const sessionUuid = req.cookies.sessionUuid;
console.log("Running cookie middleware")
if (!sessionUuid) { if (!sessionUuid) {
console.log("Found no cookie")
const newSession = await setAndPersistNewSession(res); const newSession = await setAndPersistNewSession(res);
req.cookies.sessionUuid = newSession.uuid; req.cookies.sessionUuid = newSession.uuid;
} }
if (sessionUuid) { if (sessionUuid) {
console.log(`Found a cookie ${sessionUuid}`)
if (!(await sessionService.isSessionValid(sessionUuid))) { if (!(await sessionService.isSessionValid(sessionUuid))) {
console.log("But it's not valid")
const newSession = await setAndPersistNewSession(res); const newSession = await setAndPersistNewSession(res);
req.cookies.sessionUuid = newSession.uuid; req.cookies.sessionUuid = newSession.uuid;
} }
} }
console.log("Moving on...")
next(); next();
} }

View file

@ -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;

View file

@ -45,6 +45,12 @@ class ContactDetails {
return fragment; 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; let contactDetails;
@ -67,4 +73,21 @@ window.onload = () => {
input.value = ''; 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 })
});
}
);
}; };

View file

@ -3,12 +3,14 @@ const express = require('express');
const invitesService = require('../services/invitesService'); const invitesService = require('../services/invitesService');
const nostrService = require('../services/nostrService'); const nostrService = require('../services/nostrService');
const sessionService = require('../services/sessionService'); const sessionService = require('../services/sessionService');
const profileService = require('../services/profileService');
const errors = require('../errors'); const errors = require('../errors');
const attachPublicKeyMiddleware = require('../middlewares/attachPublicKeyMiddleware');
const rejectIfNotAuthorizedMiddleware = require('../middlewares/rejectIfNotAuthorizedMiddleware');
const router = express.Router(); const router = express.Router();
router.get('/signup/nostr-challenge', async (req, res) => { router.get('/signup/nostr-challenge', async (req, res) => {
console.log("I'm heeeere")
const inviteUuid = req.cookies.inviteUuid; const inviteUuid = req.cookies.inviteUuid;
let signUpChallenge; let signUpChallenge;
@ -89,4 +91,30 @@ router.post("/signup/nostr-verify", async (req, res) => {
return res.status(200).json({ success: true }); 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; module.exports = router;

View file

@ -51,23 +51,19 @@ async function verifyNostrChallenge(signedEvent) {
const challengeTag = signedEvent.tags.find(tag => tag[0] === "challenge"); const challengeTag = signedEvent.tags.find(tag => tag[0] === "challenge");
const challenge = challengeTag[1]; const challenge = challengeTag[1];
console.log("Checking if fresh")
if (!(await isNostrChallengeFresh(challenge))) { if (!(await isNostrChallengeFresh(challenge))) {
throw TimeoutError("Challenge expired, request new one."); throw TimeoutError("Challenge expired, request new one.");
} }
console.log("Checking if completed")
if (await hasNostrChallengeBeenCompleted(challenge)) { if (await hasNostrChallengeBeenCompleted(challenge)) {
throw new errors.AlreadyUsedError("Challenge already used, request new one."); throw new errors.AlreadyUsedError("Challenge already used, request new one.");
} }
console.log("Checking if valid")
const isSignatureValid = verifyEvent(signedEvent); const isSignatureValid = verifyEvent(signedEvent);
if (!isSignatureValid) { if (!isSignatureValid) {
throw new errors.InvalidSignatureError("Signature is not valid."); throw new errors.InvalidSignatureError("Signature is not valid.");
} }
console.log("Persisting")
return await NostrChallengeCompleted.create({ return await NostrChallengeCompleted.create({
'uuid': uuid.v7(), 'uuid': uuid.v7(),
challenge: challenge, challenge: challenge,

View file

@ -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
};

View file

@ -4,7 +4,6 @@ const SessionCreated = require('../models/SessionCreated');
const SessionRelatedToPublickey = require('../models/SessionRelatedToPublickey'); const SessionRelatedToPublickey = require('../models/SessionRelatedToPublickey');
const invitesService = require('./invitesService'); const invitesService = require('./invitesService');
const constants = require('../constants'); const constants = require('../constants');
async function createSession(sessionUuid) { async function createSession(sessionUuid) {
@ -71,9 +70,23 @@ async function isSessionAuthorized(sessionUuid) {
return false; return false;
} }
async function getPublicKeyRelatedToSession(sessionUuid) {
const sessionRelatedToPublickey = await SessionRelatedToPublickey.findOne(
{
where: {
session_uuid: sessionUuid
}
}
);
return sessionRelatedToPublickey.public_key;
}
module.exports = { module.exports = {
createSession, createSession,
isSessionValid, isSessionValid,
relateSessionToPublicKey, relateSessionToPublicKey,
isSessionAuthorized isSessionAuthorized,
getPublicKeyRelatedToSession
} }

View file

@ -17,8 +17,6 @@
<hr> <hr>
<form onsubmit="return false"> <form onsubmit="return false">
<label>Pseudónimo (Nym):<input type="text" name="nym" id="nym-input"></label> <label>Pseudónimo (Nym):<input type="text" name="nym" id="nym-input"></label>
<button id="submit-details-button" type="submit">Crear tu perfil</button>
<div id="contacts"> <div id="contacts">
<p>Añade métodos de contacto para poder hablar con otros miembros.</p> <p>Añade métodos de contacto para poder hablar con otros miembros.</p>
<div class="badges"> <div class="badges">
@ -48,6 +46,7 @@
</div> </div>
</div> </div>
<button id="submit-details-button" type="submit">Crear tu perfil</button>
</form> </form>
</body> </body>