diff --git a/src/constants.js b/src/constants.js index 8bec536..79c5699 100644 --- a/src/constants.js +++ b/src/constants.js @@ -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, }; diff --git a/src/front/components/NostrSignUpButton.js b/src/front/components/NostrSignUpButton.js new file mode 100644 index 0000000..e69de29 diff --git a/src/front/pages/invite.js b/src/front/pages/invite.js index bca4e92..d8f1672 100644 --- a/src/front/pages/invite.js +++ b/src/front/pages/invite.js @@ -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(); diff --git a/src/front/services/signupService.js b/src/front/services/signupService.js new file mode 100644 index 0000000..03f2469 --- /dev/null +++ b/src/front/services/signupService.js @@ -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, +}; diff --git a/src/views/invite.ejs b/src/views/invite.ejs index d7d8f79..5319a26 100644 --- a/src/views/invite.ejs +++ b/src/views/invite.ejs @@ -21,21 +21,8 @@ />
Usa tu extensión de Nostr para darte de alta:
-