session upgrades work
This commit is contained in:
parent
bee8218e40
commit
74019e97a6
7 changed files with 146 additions and 40 deletions
|
|
@ -1,10 +1,3 @@
|
|||
class ChallengedUsedError extends Error {
|
||||
constructor(message) {
|
||||
super(message);
|
||||
this.name = "ChallengeUsedError";
|
||||
}
|
||||
}
|
||||
|
||||
class AlreadyUsedError extends Error {
|
||||
constructor(message) {
|
||||
super(message);
|
||||
|
|
@ -19,13 +12,6 @@ class InvalidSignatureError extends Error {
|
|||
}
|
||||
}
|
||||
|
||||
class AppInvitedUsedError extends Error {
|
||||
constructor(message) {
|
||||
super(message);
|
||||
this.name = "AppInvitedUsedError";
|
||||
}
|
||||
}
|
||||
|
||||
class NotFoundError extends Error {
|
||||
constructor(message) {
|
||||
super(message);
|
||||
|
|
@ -33,8 +19,16 @@ class NotFoundError extends Error {
|
|||
}
|
||||
}
|
||||
|
||||
class ExpiredError extends Error {
|
||||
constructor(message) {
|
||||
super(message);
|
||||
this.name = 'ExpiredError';
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
AlreadyUsedError,
|
||||
InvalidSignatureError,
|
||||
NotFoundError
|
||||
NotFoundError,
|
||||
ExpiredError
|
||||
};
|
||||
|
|
@ -11,16 +11,24 @@ async function setAndPersistNewSession(res) {
|
|||
|
||||
async function createSessionMiddleware(req, res, next) {
|
||||
|
||||
if (!req.cookies.sessionUuid) {
|
||||
const sessionUuid = req.cookies.sessionUuid;
|
||||
|
||||
console.log("Running cookie middleware")
|
||||
|
||||
if (!sessionUuid) {
|
||||
console.log("Found no cookie")
|
||||
await setAndPersistNewSession(res);
|
||||
}
|
||||
|
||||
if (req.cookies.sessionUuid) {
|
||||
if (await sessionService.isSessionExpired(req.cookies.sessionUuid)) {
|
||||
if (sessionUuid) {
|
||||
console.log(`Found a cookie ${sessionUuid}`)
|
||||
if (!(await sessionService.isSessionValid(sessionUuid))) {
|
||||
console.log("But it's not valid")
|
||||
await setAndPersistNewSession(res);
|
||||
}
|
||||
}
|
||||
|
||||
console.log("Moving on...")
|
||||
next();
|
||||
}
|
||||
|
||||
|
|
|
|||
27
src/models/SessionRelatedToPublickey.js
Normal file
27
src/models/SessionRelatedToPublickey.js
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
const { DataTypes } = require('sequelize');
|
||||
const sequelize = require('../database');
|
||||
|
||||
const SessionRelatedToPublickey = sequelize.define('SessionRelatedToPublickey', {
|
||||
uuid: {
|
||||
type: DataTypes.UUID,
|
||||
allowNull: false,
|
||||
unique: true,
|
||||
primaryKey: true
|
||||
},
|
||||
session_uuid: {
|
||||
type: DataTypes.UUID,
|
||||
allowNull: false,
|
||||
},
|
||||
public_key: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false
|
||||
},
|
||||
created_at: {
|
||||
type: DataTypes.DATE,
|
||||
allowNull: false
|
||||
}
|
||||
}, {
|
||||
tableName: 'session_related_to_public_key'
|
||||
});
|
||||
|
||||
module.exports = SessionRelatedToPublickey;
|
||||
|
|
@ -2,6 +2,7 @@ const express = require('express');
|
|||
|
||||
const invitesService = require('../services/invitesService');
|
||||
const nostrService = require('../services/nostrService');
|
||||
const sessionService = require('../services/sessionService');
|
||||
const { TimeoutError } = require('sequelize');
|
||||
const errors = require('../errors');
|
||||
|
||||
|
|
@ -55,22 +56,37 @@ router.get('/signup/nostr-challenge', async (req, res) => {
|
|||
|
||||
router.post("/signup/nostr-verify", async (req, res) => {
|
||||
const signedEvent = req.body;
|
||||
const sessionUuid = req.cookies.sessionUuid;
|
||||
|
||||
let completedSignUpChallenge;
|
||||
try {
|
||||
console.log(`Starting nostr-verify with event: ${signedEvent}`);
|
||||
const completedSignUpChallenge = await invitesService.verifySignUpChallenge(signedEvent);
|
||||
console.log(`Finished nostr-verify`);
|
||||
completedSignUpChallenge = await invitesService.verifySignUpChallenge(signedEvent);
|
||||
} catch (error) {
|
||||
if (error instanceof TimeoutError) {
|
||||
console.error('The challenge is outdated.');
|
||||
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) {
|
||||
console.error('The challenge was already used, request a new one.');
|
||||
return res.status(410).json({
|
||||
success: false,
|
||||
message: 'The challenge has been used, request a new one.'
|
||||
})
|
||||
}
|
||||
if (error instanceof errors.InvalidSignatureError) {
|
||||
console.error('Signature is not valid.')
|
||||
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 });
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -32,6 +32,30 @@ router.get('/invite/:inviteUuid', async (req, res) => {
|
|||
return res.render('invite', { invite });
|
||||
});
|
||||
|
||||
router.get('/invite/:inviteUuid', async (req, res) => {
|
||||
const { inviteUuid } = req.params;
|
||||
|
||||
res.cookie('inviteUuid', inviteUuid, { httpOnly: true, maxAge: 86400000 });
|
||||
|
||||
let invite;
|
||||
try {
|
||||
invite = await invitesService.getAppInvite(inviteUuid);
|
||||
if (!invite) {
|
||||
return res.status(404).render('error', { message: 'Invite not found.' });
|
||||
}
|
||||
|
||||
if (await invitesService.isAppInviteSpent(inviteUuid)) {
|
||||
return res.status(410).render('invite_spent', { 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) => {
|
||||
res.render('private', {});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -73,22 +73,17 @@ async function verifySignUpChallenge(signedEvent) {
|
|||
null, challenge
|
||||
);
|
||||
|
||||
console.log(`Found this nostr challenge: ${nostrChallenge}`);
|
||||
|
||||
const signUpChallenge = await SignUpChallengeCreated.findOne({
|
||||
where: {
|
||||
nostr_challenge_uuid: nostrChallenge.uuid
|
||||
}
|
||||
})
|
||||
|
||||
console.log(`Found this signup challenge: ${signUpChallenge}`);
|
||||
|
||||
if (await nostrService.hasNostrChallengeBeenCompleted(challenge)) {
|
||||
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);
|
||||
console.log(`Verified the NostrChallenge: ${completedNostrChallenge}`);
|
||||
|
||||
const completedSignUpChallenge = await SignUpChallengeCompleted.create(
|
||||
{
|
||||
|
|
@ -99,17 +94,33 @@ async function verifySignUpChallenge(signedEvent) {
|
|||
created_at: new Date().toISOString()
|
||||
}
|
||||
);
|
||||
console.log(`Verified the SignUpChallenge: ${completedSignUpChallenge}`);
|
||||
|
||||
|
||||
return completedSignUpChallenge;
|
||||
}
|
||||
|
||||
async function isPublicKeySignedUp(publicKey) {
|
||||
const signUpChallengeCompleted = await SignUpChallengeCompleted.findOne(
|
||||
{
|
||||
where: {
|
||||
public_key: publicKey
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
if (signUpChallengeCompleted) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
appInviteExists,
|
||||
getAppInvite,
|
||||
isAppInviteSpent,
|
||||
createAppInvite,
|
||||
createSignUpChallenge,
|
||||
verifySignUpChallenge
|
||||
verifySignUpChallenge,
|
||||
isPublicKeySignedUp
|
||||
};
|
||||
|
|
@ -1,4 +1,9 @@
|
|||
const uuid = require('uuid');
|
||||
|
||||
const SessionCreated = require('../models/SessionCreated');
|
||||
const SessionRelatedToPublickey = require('../models/SessionRelatedToPublickey');
|
||||
|
||||
const invitesService = require('./invitesService');
|
||||
|
||||
const constants = require('../constants');
|
||||
|
||||
|
|
@ -14,7 +19,7 @@ async function createSession(sessionUuid) {
|
|||
});
|
||||
}
|
||||
|
||||
async function isSessionExpired(sessionUuid) {
|
||||
async function isSessionValid(sessionUuid) {
|
||||
const currentSession = await SessionCreated.findOne({
|
||||
where: {
|
||||
'uuid': sessionUuid
|
||||
|
|
@ -22,15 +27,36 @@ async function isSessionExpired(sessionUuid) {
|
|||
});
|
||||
|
||||
if (!currentSession) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (currentSession.expires_at <= new Date()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
exports.createSession = createSession;
|
||||
exports.isSessionExpired = isSessionExpired;
|
||||
if (currentSession.expires_at <= new Date()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
async function relateSessionToPublicKey(sessionUuid, publicKey) {
|
||||
if (!(await isSessionValid(sessionUuid))) {
|
||||
throw Error("Session is not valid anymore.");
|
||||
}
|
||||
|
||||
if (!(await invitesService.isPublicKeySignedUp(publicKey))) {
|
||||
throw Error("Public key is not signed up.");
|
||||
}
|
||||
|
||||
return SessionRelatedToPublickey.create({
|
||||
'uuid': uuid.v7(),
|
||||
session_uuid: sessionUuid,
|
||||
public_key: publicKey,
|
||||
created_at: new Date().toISOString()
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
createSession,
|
||||
isSessionValid,
|
||||
relateSessionToPublicKey
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue