stuff really

This commit is contained in:
counterweight 2025-03-13 15:36:00 +01:00
parent 8131de0c96
commit 545c54bf81
Signed by: counterweight
GPG key ID: 883EDBAA726BD96C
5 changed files with 130 additions and 76 deletions

View file

@ -1,7 +1,14 @@
const DEFAULT_SESSION_DURATION_SECONDS = 60 * 60 * 24 * 30;
const DEFAULT_NOSTR_CHALLENGE_DURATION_SECONDS = 60 * 60 * 24 * 30;
const DEFAULT_REDIRECT_DELAY = 3 * 1000; // 3seconds times milliseconds;
const API_PATHS = {
createProfile: '/createProfile',
};
module.exports = {
DEFAULT_SESSION_DURATION_SECONDS,
DEFAULT_NOSTR_CHALLENGE_DURATION_SECONDS,
API_PATHS,
DEFAULT_REDIRECT_DELAY,
};

View file

@ -1,6 +1,63 @@
const checkNostrExtension = require('../utils/checkNostrExtension');
const signupService = require('../services/signupService');
const constants = require('../../constants');
class NostrSignupButton {
constructor({ parentElement, id, onClickCallback }) {
this.element = null;
this.parentElement = parentElement;
this.id = id;
this.onClickCallback = onClickCallback;
}
render() {
const thisButton = document.createElement('button');
thisButton.id = this.id;
thisButton.type = 'submit';
thisButton.className = 'button-large button-nostr';
const figure = document.createElement('figure');
const img = document.createElement('img');
img.src = '/img/white_ostrich.svg';
img.style.width = '40%';
img.style.margin = '-5% -5%';
figure.appendChild(img);
const paragraph = document.createElement('p');
paragraph.textContent = 'Alta con Nostr';
thisButton.appendChild(figure);
thisButton.appendChild(paragraph);
thisButton.addEventListener('click', () => {
this.onClickCallback();
});
this.element = thisButton;
this.parentElement.appendChild(this.element);
}
disable() {
this.element.disabled = true;
}
}
const nostrSignupArea = document.getElementById('nostr-signup-area');
const noExtensionNudges = document.getElementById('no-extension-nudges');
const signUpSuccessNotification = document.getElementById('sign-up-success');
const invitesFunction = () => {
const signupButton = new NostrSignupButton({
parentElement: nostrSignupArea,
id: 'nostr-signup-button',
onClickCallback: () => {
acceptInvite();
},
});
signupButton.render();
window.onload = () => {
checkNostrExtension(
window,
@ -9,81 +66,27 @@ const invitesFunction = () => {
},
() => {
console.log('Nostr extension not present');
document.querySelector('#nostr-signup-button').disabled = true;
document.querySelector('#no-extension-nudges').style.display = 'block';
signupButton.disable();
noExtensionNudges.style.display = 'block';
}
);
};
const signUpConfirmation = document.querySelector('#sign-up-success');
function showConfirmationAndRedirect() {
signUpConfirmation.classList.add('revealed');
signUpSuccessNotification.classList.add('revealed');
setTimeout(() => {
window.location.href = '/createProfile';
}, 5000);
window.location.href = constants.API_PATHS.createProfile;
}, constants.DEFAULT_REDIRECT_DELAY);
}
async function acceptInvite() {
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 {
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,
};
let signedEvent;
try {
signedEvent = await window.nostr.signEvent(event);
} catch (error) {
document.querySelector('#rejected-nostr-nudges').style.display = 'block';
return;
}
let verifyResponse;
try {
verifyResponse = await fetch('/api/signup/nostr-verify', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(signedEvent),
});
} catch (error) {
console.log(`Something went wrong: ${error}`);
return;
}
const verifyResponse =
await signupService.requestAndRespondSignUpChallenge();
if (verifyResponse.ok) {
showConfirmationAndRedirect();
}
}
const signUpButton = document.getElementById('nostr-signup-button');
signUpButton.addEventListener('click', () => {
acceptInvite();
});
};
invitesFunction();

View file

@ -0,0 +1,57 @@
const requestAndRespondSignUpChallenge = async () => {
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 {
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,
};
let signedEvent;
try {
signedEvent = await window.nostr.signEvent(event);
} catch (error) {
document.querySelector('#rejected-nostr-nudges').style.display = 'block';
return;
}
let verifyResponse;
try {
verifyResponse = await fetch('/api/signup/nostr-verify', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(signedEvent),
});
} catch (error) {
console.log(`Something went wrong: ${error}`);
return;
}
return verifyResponse;
};
module.exports = {
requestAndRespondSignUpChallenge,
};

View file

@ -21,21 +21,8 @@
/>
</figure>
<p>Usa tu extensión de Nostr para darte de alta:</p>
<div>
<button
id="nostr-signup-button"
type="submit"
class="button-large button-nostr"
>
<figure>
<img
src="/img/white_ostrich.svg"
width="40%"
margin="-5% -5%"
/>
</figure>
<p>Alta con Nostr</p>
</button>
<div id="nostr-signup-area">
</div>
<div
id="rejected-nostr-nudges"