- aggiornata la grafica della Home di RISO
- Profilo Completition - Email Verificata - Invita un Amico (invio di email)
This commit is contained in:
@@ -29,7 +29,7 @@ GCM_API_KEY=""
|
|||||||
PROD=0
|
PROD=0
|
||||||
PROJECT_DESCR_MAIN='__PROJECTS'
|
PROJECT_DESCR_MAIN='__PROJECTS'
|
||||||
SECRK=Askb38v23jjDFaoskBOWj92axXCQ
|
SECRK=Askb38v23jjDFaoskBOWj92axXCQ
|
||||||
TOKEN_LIFE=10m
|
TOKEN_LIFE=30m
|
||||||
REFRESH_TOKEN_LIFE=14d
|
REFRESH_TOKEN_LIFE=14d
|
||||||
FTPSERVER_HOST=139.162.166.31
|
FTPSERVER_HOST=139.162.166.31
|
||||||
FTPSERVER_PORT=21
|
FTPSERVER_PORT=21
|
||||||
|
|||||||
6
.vscode/launch.json
vendored
6
.vscode/launch.json
vendored
@@ -13,7 +13,7 @@
|
|||||||
"--inspect=9229" // Use "--inspect=0.0.0.0:9229" for remote debugging
|
"--inspect=9229" // Use "--inspect=0.0.0.0:9229" for remote debugging
|
||||||
],
|
],
|
||||||
"args": [
|
"args": [
|
||||||
"${workspaceFolder}/src/server/server.js"
|
"${workspaceFolder}/src/server.js"
|
||||||
], // Replace with your entry file
|
], // Replace with your entry file
|
||||||
"cwd": "${workspaceFolder}",
|
"cwd": "${workspaceFolder}",
|
||||||
"autoAttachChildProcesses": true,
|
"autoAttachChildProcesses": true,
|
||||||
@@ -36,7 +36,7 @@
|
|||||||
"--trace-warnings" // Use "--inspect=0.0.0.0:9229" for remote debugging
|
"--trace-warnings" // Use "--inspect=0.0.0.0:9229" for remote debugging
|
||||||
],
|
],
|
||||||
"args": [
|
"args": [
|
||||||
"${workspaceFolder}/src/server/server.js"
|
"${workspaceFolder}/src/server.js"
|
||||||
], // Replace with your entry file
|
], // Replace with your entry file
|
||||||
"cwd": "${workspaceFolder}",
|
"cwd": "${workspaceFolder}",
|
||||||
"autoAttachChildProcesses": true,
|
"autoAttachChildProcesses": true,
|
||||||
@@ -50,7 +50,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "ServerSide",
|
"name": "ServerSide",
|
||||||
"program": "${workspaceFolder}/src/server/server.js",
|
"program": "${workspaceFolder}/src/server.js",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"skipFiles": [
|
"skipFiles": [
|
||||||
"<node_internals>/**"
|
"<node_internals>/**"
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ yarn
|
|||||||
|
|
||||||
### Start the app in development mode (hot-code reloading, error reporting, etc.)
|
### Start the app in development mode (hot-code reloading, error reporting, etc.)
|
||||||
```bash
|
```bash
|
||||||
node src/server/server.js
|
node src/server.js
|
||||||
```
|
```
|
||||||
|
|
||||||
### Creating the ambient test
|
### Creating the ambient test
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ module.exports = {
|
|||||||
apps : [
|
apps : [
|
||||||
{
|
{
|
||||||
name: "FreePlanetServerSide",
|
name: "FreePlanetServerSide",
|
||||||
script: "./src/server/server.js",
|
script: "./src/server.js",
|
||||||
ignore_watch : ["node_modules"],
|
ignore_watch : ["node_modules"],
|
||||||
watch: false,
|
watch: false,
|
||||||
//autorestart: true,
|
//autorestart: true,
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ module.exports = {
|
|||||||
apps: [
|
apps: [
|
||||||
{
|
{
|
||||||
name: "PCB-PROD",
|
name: "PCB-PROD",
|
||||||
script: "/var/www/nodejs_piuchebuono_server/src/server/server.js",
|
script: "/var/www/nodejs_piuchebuono_server/src/server.js",
|
||||||
ignore_watch: ["node_modules", "logs"],
|
ignore_watch: ["node_modules", "logs"],
|
||||||
// interpreter: "/root/.nvm/versions/node/v22.13.1/bin/node",
|
// interpreter: "/root/.nvm/versions/node/v22.13.1/bin/node",
|
||||||
//autorestart: true,
|
//autorestart: true,
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ module.exports = {
|
|||||||
apps: [
|
apps: [
|
||||||
{
|
{
|
||||||
name: "PCB-TEST",
|
name: "PCB-TEST",
|
||||||
script: "/var/www/nodejs_test.piuchebuono_server/src/server/server.js",
|
script: "/var/www/nodejs_test.piuchebuono_server/src/server.js",
|
||||||
ignore_watch: ["node_modules", "logs"],
|
ignore_watch: ["node_modules", "logs"],
|
||||||
// interpreter: "/root/.nvm/versions/node/v22.13.1/bin/node",
|
// interpreter: "/root/.nvm/versions/node/v22.13.1/bin/node",
|
||||||
instances: 1,
|
instances: 1,
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ module.exports = {
|
|||||||
apps: [
|
apps: [
|
||||||
{
|
{
|
||||||
name: "PRODUZIONE - FREEPLANET",
|
name: "PRODUZIONE - FREEPLANET",
|
||||||
script: "/var/www/www.freeplanet_server/src/server/server.js",
|
script: "/var/www/www.freeplanet_server/src/server.js",
|
||||||
ignore_watch: ["node_modules", "logs"],
|
ignore_watch: ["node_modules", "logs"],
|
||||||
// interpreter: "/root/.nvm/versions/node/v16.19.0/bin/node",
|
// interpreter: "/root/.nvm/versions/node/v16.19.0/bin/node",
|
||||||
//autorestart: true,
|
//autorestart: true,
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ module.exports = {
|
|||||||
apps: [
|
apps: [
|
||||||
{
|
{
|
||||||
name: "RISO-PROD",
|
name: "RISO-PROD",
|
||||||
script: "/var/www/nodejs_riso_server/src/server/server.js",
|
script: "/var/www/nodejs_riso_server/src/server.js",
|
||||||
ignore_watch: ["node_modules", "logs"],
|
ignore_watch: ["node_modules", "logs"],
|
||||||
// interpreter: "/root/.nvm/versions/node/v22.13.1/bin/node",
|
// interpreter: "/root/.nvm/versions/node/v22.13.1/bin/node",
|
||||||
//autorestart: true,
|
//autorestart: true,
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ module.exports = {
|
|||||||
apps: [
|
apps: [
|
||||||
{
|
{
|
||||||
name: "RISO-TEST",
|
name: "RISO-TEST",
|
||||||
script: "./src/server/server.js",
|
script: "./src/server.js",
|
||||||
ignore_watch: ["node_modules", "logs"],
|
ignore_watch: ["node_modules", "logs"],
|
||||||
// interpreter: "/root/.nvm/versions/node/v22.13.1/bin/node",
|
// interpreter: "/root/.nvm/versions/node/v22.13.1/bin/node",
|
||||||
watch: false,
|
watch: false,
|
||||||
|
|||||||
BIN
emails/.DS_Store
vendored
BIN
emails/.DS_Store
vendored
Binary file not shown.
@@ -1,71 +0,0 @@
|
|||||||
p #{username} (#{name} #{surname}) si è appena Iscritto ad Arcadei Foundation su #{nomeapp}
|
|
||||||
p Con i seguenti dati di accesso:
|
|
||||||
span Nome:
|
|
||||||
strong #{iscritto.name}<br>
|
|
||||||
span Cognome:
|
|
||||||
strong #{iscritto.surname}<br>
|
|
||||||
span Email:
|
|
||||||
strong #{iscritto.email}<br>
|
|
||||||
span Email Secondaria:
|
|
||||||
strong #{iscritto.email2}<br>
|
|
||||||
span Indirizzo di Residenza:
|
|
||||||
strong #{iscritto.residency_address}<br>
|
|
||||||
span Città di Residenza:
|
|
||||||
strong #{iscritto.residency_city}<br>
|
|
||||||
span Provincia:
|
|
||||||
strong #{iscritto.residency_province}<br>
|
|
||||||
span CAP:
|
|
||||||
strong #{iscritto.residency_zipcode}<br>
|
|
||||||
span Nazione:
|
|
||||||
strong #{iscritto.residency_country}<br>
|
|
||||||
span Data di Nascita:
|
|
||||||
strong #{data_nascita}<br>
|
|
||||||
span Città di Nascita:
|
|
||||||
strong #{iscritto.born_city}<br>
|
|
||||||
span Provincia di Nascita:
|
|
||||||
strong #{iscritto.born_province}<br>
|
|
||||||
span Paese di Nascita:
|
|
||||||
strong #{iscritto.born_country}<br>
|
|
||||||
span Telefono:
|
|
||||||
strong #{iscritto.cell_phone}<br>
|
|
||||||
span Telefono2:
|
|
||||||
strong #{iscritto.cell_phone2}<br>
|
|
||||||
span Tipo di Documento :
|
|
||||||
strong #{iscritto.doctype}<br>
|
|
||||||
span Numero Documento :
|
|
||||||
strong #{iscritto.documentnumber}<br>
|
|
||||||
span Metodo di Pagamento :
|
|
||||||
strong #{iscritto.metodo_pagamento}<br>
|
|
||||||
span Quota scelta da versare :
|
|
||||||
strong #{iscritto.quota_versata}<br>
|
|
||||||
span Scrivi altre eventuali informazioni o comunicazioni:
|
|
||||||
strong #{iscritto.altre_comunicazioni}<br>
|
|
||||||
span Categorie d'Interesse :
|
|
||||||
strong #{iscritto.categorie_interesse}<br>
|
|
||||||
p <br>Saluti
|
|
||||||
|
|
||||||
style(type="text/css").
|
|
||||||
html, body {
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
p {
|
|
||||||
font-size: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.divbtn {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-lg {
|
|
||||||
padding: 5px;
|
|
||||||
margin: 5px;
|
|
||||||
font-size: 26px;
|
|
||||||
cursor: pointer;
|
|
||||||
color: white;
|
|
||||||
background: #027be3 !important;
|
|
||||||
border-radius: 28px;
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
=`Nuova Iscrizione Arcadei di ${name} ${surname} (${emailto}) su ${nomeapp}`
|
|
||||||
@@ -1,42 +1,179 @@
|
|||||||
p #{username} (#{name} #{surname}) si è appena Registrato su #{nomeapp}
|
doctype html
|
||||||
p Con i seguenti dati di accesso:
|
html(lang="it")
|
||||||
span Username:
|
head
|
||||||
strong #{username}<br>
|
meta(charset="UTF-8")
|
||||||
span Email:
|
meta(name="viewport" content="width=device-width, initial-scale=1.0")
|
||||||
strong #{emailto}<br>
|
style(type="text/css").
|
||||||
span Invitante:
|
* {
|
||||||
strong #{aportador_solidario}<br>
|
|
||||||
span Nome:
|
|
||||||
strong #{user.name}<br>
|
|
||||||
span Cognome:
|
|
||||||
strong #{user.surname}<br>
|
|
||||||
span Cellulare:
|
|
||||||
strong #{user.profile.intcode_cell} #{user.profile.cell}<br>
|
|
||||||
span Nazionalità:
|
|
||||||
strong #{user.profile.nationality}<br>
|
|
||||||
span Gruppo:
|
|
||||||
strong #{idMyGroup}<br>
|
|
||||||
p <br>Saluti
|
|
||||||
|
|
||||||
style(type="text/css").
|
|
||||||
html, body {
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
.divbtn {
|
body {
|
||||||
display: flex;
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
||||||
align-items: center;
|
background-color: #f5f5f5;
|
||||||
justify-content: center;
|
padding: 20px;
|
||||||
|
line-height: 1.6;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-lg {
|
.email-container {
|
||||||
padding: 5px;
|
max-width: 600px;
|
||||||
margin: 5px;
|
margin: 0 auto;
|
||||||
font-size: 26px;
|
background: white;
|
||||||
cursor: pointer;
|
border-radius: 12px;
|
||||||
|
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.email-header {
|
||||||
|
background: linear-gradient(135deg, #027be3 0%, #0056b3 100%);
|
||||||
color: white;
|
color: white;
|
||||||
background: #027be3 !important;
|
padding: 32px 24px;
|
||||||
border-radius: 28px;
|
text-align: center;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.email-header h1 {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.email-header p {
|
||||||
|
margin: 8px 0 0 0;
|
||||||
|
font-size: 14px;
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.email-body {
|
||||||
|
padding: 32px 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-info {
|
||||||
|
background: #f8f9fa;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 20px;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-row {
|
||||||
|
display: flex;
|
||||||
|
padding: 10px 0;
|
||||||
|
border-bottom: 1px solid #e0e0e0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-row:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-label {
|
||||||
|
font-weight: 600;
|
||||||
|
color: #555;
|
||||||
|
min-width: 140px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-value {
|
||||||
|
color: #1a1a1a;
|
||||||
|
font-size: 14px;
|
||||||
|
flex: 1;
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
.email-footer {
|
||||||
|
padding: 24px;
|
||||||
|
text-align: center;
|
||||||
|
background: #f8f9fa;
|
||||||
|
color: #777;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.highlight {
|
||||||
|
display: inline-block;
|
||||||
|
background: #e3f2fd;
|
||||||
|
color: #027be3;
|
||||||
|
padding: 2px 8px;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media only screen and (max-width: 600px) {
|
||||||
|
body {
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.email-header {
|
||||||
|
padding: 24px 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.email-body {
|
||||||
|
padding: 24px 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-row {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-label {
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
body
|
||||||
|
.email-container
|
||||||
|
.email-header
|
||||||
|
h1 ✓ Nuova Registrazione su #{nomeapp}
|
||||||
|
p #{nomeapp || 'Piattaforma'}
|
||||||
|
|
||||||
|
.email-body
|
||||||
|
p(style="margin-bottom: 20px; font-size: 15px; color: #333;")
|
||||||
|
| L'utente
|
||||||
|
span.highlight #{username || 'N/D'}
|
||||||
|
| si è appena registrato sulla piattaforma #{nomeapp}.
|
||||||
|
|
||||||
|
.user-info
|
||||||
|
if username
|
||||||
|
.info-row
|
||||||
|
.info-label Username:
|
||||||
|
.info-value #{username}
|
||||||
|
|
||||||
|
if emailto
|
||||||
|
.info-row
|
||||||
|
.info-label Email:
|
||||||
|
.info-value #{emailto}
|
||||||
|
|
||||||
|
if user && user.name
|
||||||
|
.info-row
|
||||||
|
.info-label Nome:
|
||||||
|
.info-value #{user.name}
|
||||||
|
|
||||||
|
if user && user.surname
|
||||||
|
.info-row
|
||||||
|
.info-label Cognome:
|
||||||
|
.info-value #{user.surname}
|
||||||
|
|
||||||
|
if user && user.profile && (user.profile.cell || user.profile.intcode_cell)
|
||||||
|
.info-row
|
||||||
|
.info-label Cellulare:
|
||||||
|
.info-value
|
||||||
|
| #{user.profile.intcode_cell || ''} #{user.profile.cell || ''}
|
||||||
|
|
||||||
|
if user && user.profile && user.profile.nationality
|
||||||
|
.info-row
|
||||||
|
.info-label Nazionalità:
|
||||||
|
.info-value #{user.profile.nationality}
|
||||||
|
|
||||||
|
if aportador_solidario
|
||||||
|
.info-row
|
||||||
|
.info-label Invitante:
|
||||||
|
.info-value #{aportador_solidario}
|
||||||
|
|
||||||
|
if idMyGroup
|
||||||
|
.info-row
|
||||||
|
.info-label Gruppo:
|
||||||
|
.info-value #{idMyGroup}
|
||||||
|
|
||||||
|
.email-footer
|
||||||
|
p Questa è una email automatica di notifica
|
||||||
|
p(style="margin-top: 8px; font-size: 12px;")
|
||||||
|
| © #{new Date().getFullYear()} #{nomeapp || ''}.
|
||||||
@@ -19,7 +19,6 @@ html
|
|||||||
}
|
}
|
||||||
|
|
||||||
body(yahoofix, style="background: #ffffff")
|
body(yahoofix, style="background: #ffffff")
|
||||||
- var baseimg = baseurl + '/statics/'
|
|
||||||
span(id='body_style', style='display:block')
|
span(id='body_style', style='display:block')
|
||||||
table(cellpadding="10", cellspacing="0", width="600", align="center")
|
table(cellpadding="10", cellspacing="0", width="600", align="center")
|
||||||
tr
|
tr
|
||||||
|
|||||||
417
emails/invitaamico/it/html.pug
Normal file
417
emails/invitaamico/it/html.pug
Normal file
@@ -0,0 +1,417 @@
|
|||||||
|
doctype html
|
||||||
|
html(lang="it")
|
||||||
|
head
|
||||||
|
meta(charset="UTF-8")
|
||||||
|
meta(name="viewport" content="width=device-width, initial-scale=1.0")
|
||||||
|
style(type="text/css").
|
||||||
|
* {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
padding: 20px;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-logo {
|
||||||
|
width: 120px;
|
||||||
|
height: auto;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
display: block;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.email-container {
|
||||||
|
max-width: 600px;
|
||||||
|
margin: 0 auto;
|
||||||
|
background: white;
|
||||||
|
border-radius: 12px;
|
||||||
|
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.email-header {
|
||||||
|
background: linear-gradient(135deg, #f4a460 0%, #d2691e 100%);
|
||||||
|
color: white;
|
||||||
|
padding: 40px 24px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.email-header h1 {
|
||||||
|
margin: 0 0 8px 0;
|
||||||
|
font-size: 26px;
|
||||||
|
font-weight: 600;
|
||||||
|
line-height: 1.3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.email-header .subtitle {
|
||||||
|
margin: 8px 0 0 0;
|
||||||
|
font-size: 15px;
|
||||||
|
opacity: 0.95;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.welcome-icon {
|
||||||
|
font-size: 48px;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.email-body {
|
||||||
|
padding: 32px 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.intro-text {
|
||||||
|
font-size: 16px;
|
||||||
|
color: #333;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 1.7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.highlight-box {
|
||||||
|
background: #fff8dc;
|
||||||
|
border-left: 4px solid #f4a460;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 16px;
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.highlight-box p {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 15px;
|
||||||
|
color: #1a1a1a;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.riso-info {
|
||||||
|
background: #fef9f3;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 16px;
|
||||||
|
margin: 20px 0;
|
||||||
|
border: 1px solid #f4a460;
|
||||||
|
}
|
||||||
|
|
||||||
|
.riso-info h3 {
|
||||||
|
font-size: 16px;
|
||||||
|
color: #d2691e;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.riso-info p {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #555;
|
||||||
|
line-height: 1.6;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.benefits-list {
|
||||||
|
background: #f8f9fa;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 16px;
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.benefits-list h3 {
|
||||||
|
font-size: 17px;
|
||||||
|
color: #1a1a1a;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
text-align: center;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.benefit-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
padding: 6px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.benefit-icon {
|
||||||
|
font-size: 20px;
|
||||||
|
margin-right: 10px;
|
||||||
|
min-width: 24px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.benefit-text {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #555;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.values-section {
|
||||||
|
background: linear-gradient(135deg, #fff8dc 0%, #fef9f3 100%);
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 16px;
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.values-section h3 {
|
||||||
|
font-size: 16px;
|
||||||
|
color: #d2691e;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
text-align: center;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.value-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #555;
|
||||||
|
}
|
||||||
|
|
||||||
|
.value-item strong {
|
||||||
|
color: #d2691e;
|
||||||
|
margin-right: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cta-section {
|
||||||
|
text-align: center;
|
||||||
|
margin: 24px 0;
|
||||||
|
padding: 20px 0;
|
||||||
|
border-top: 1px solid #e0e0e0;
|
||||||
|
border-bottom: 1px solid #e0e0e0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cta-title {
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #1a1a1a;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cta-button {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 16px 48px;
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: white;
|
||||||
|
background: linear-gradient(135deg, #f4a460 0%, #d2691e 100%);
|
||||||
|
border-radius: 50px;
|
||||||
|
text-decoration: none;
|
||||||
|
box-shadow: 0 4px 12px rgba(210, 105, 30, 0.3);
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-box {
|
||||||
|
background: #e8f5e9;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 14px;
|
||||||
|
margin-top: 20px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-box p {
|
||||||
|
margin: 0;
|
||||||
|
color: #2e7d32;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.telegram-box {
|
||||||
|
background: #e3f2fd;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 14px;
|
||||||
|
margin: 16px 0;
|
||||||
|
text-align: center;
|
||||||
|
border: 1px solid #64b5f6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.telegram-box p {
|
||||||
|
margin: 0;
|
||||||
|
color: #1976d2;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.telegram-box strong {
|
||||||
|
color: #0d47a1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.link-box {
|
||||||
|
background: #fff3e0;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 12px;
|
||||||
|
margin: 16px 0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.link-box a {
|
||||||
|
color: #d2691e;
|
||||||
|
text-decoration: none;
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.email-footer {
|
||||||
|
padding: 20px;
|
||||||
|
text-align: center;
|
||||||
|
background: #f8f9fa;
|
||||||
|
color: #777;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.email-footer p {
|
||||||
|
margin: 4px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.divider {
|
||||||
|
height: 1px;
|
||||||
|
background: linear-gradient(to right, transparent, #e0e0e0, transparent);
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media only screen and (max-width: 600px) {
|
||||||
|
body {
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.email-header {
|
||||||
|
padding: 24px 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.email-header h1 {
|
||||||
|
font-size: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.email-body {
|
||||||
|
padding: 20px 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cta-button {
|
||||||
|
padding: 14px 32px;
|
||||||
|
font-size: 16px;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.benefit-item, .value-item {
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
body
|
||||||
|
.email-container
|
||||||
|
//- Header
|
||||||
|
.email-header
|
||||||
|
img.header-logo(src=baseurl+'/images/logo.png' alt='RISO - Rete Italiana Scambi Orizzontali')
|
||||||
|
h1 Sei stato invitato ad unirti a #{nomeapp}!
|
||||||
|
p.subtitle Rete Italiana Scambi Orizzontali
|
||||||
|
|
||||||
|
//- Body
|
||||||
|
.email-body
|
||||||
|
//- Intro
|
||||||
|
.intro-text
|
||||||
|
if usernameInvitante
|
||||||
|
| <strong>#{usernameInvitante}</strong> ti ha invitato a far parte della comunità RISO, una rete di persone che credono in un'economia basata su fiducia, comunità e scambi solidali.
|
||||||
|
else
|
||||||
|
| Hai ricevuto un invito speciale per unirti alla comunità RISO, una rete di persone che credono in un'economia basata su fiducia, comunità e scambi solidali.
|
||||||
|
|
||||||
|
//- Messaggio personalizzato
|
||||||
|
if messaggioPersonalizzato
|
||||||
|
.highlight-box
|
||||||
|
p
|
||||||
|
| 💌 <strong>Messaggio da #{usernameInvitante}:</strong><br>
|
||||||
|
| "#{messaggioPersonalizzato}"
|
||||||
|
|
||||||
|
//- Cos'è RISO
|
||||||
|
.riso-info
|
||||||
|
h3 🍚 Cos'è il Progetto RISO?
|
||||||
|
p
|
||||||
|
| RISO è una <strong>rete di comunità territoriali</strong> in tutta Italia dove puoi scambiare beni, servizi e ospitalità con altre persone, usando il <strong>baratto, il dono</strong>, oppure la moneta complementare <strong>RIS</strong>.
|
||||||
|
p
|
||||||
|
| Non è un marketplace commerciale: è una <strong>comunità basata su fiducia e relazioni</strong> reali tra persone che si conoscono e si incontrano.
|
||||||
|
|
||||||
|
//- Benefici
|
||||||
|
.benefits-list
|
||||||
|
h3 ✨ Cosa puoi fare con RISO
|
||||||
|
.benefit-item
|
||||||
|
span.benefit-icon 🔄
|
||||||
|
span.benefit-text Scambiare beni, servizi e ospitalità con baratto, dono, RIS o Euro
|
||||||
|
.benefit-item
|
||||||
|
span.benefit-icon 🤝
|
||||||
|
span.benefit-text Connetterti con la tua comunità territoriale locale (circuito provinciale)
|
||||||
|
.benefit-item
|
||||||
|
span.benefit-icon 💰
|
||||||
|
span.benefit-text Usare i RIS, una moneta complementare che parte da zero (nessun debito iniziale!)
|
||||||
|
.benefit-item
|
||||||
|
span.benefit-icon 🌱
|
||||||
|
span.benefit-text Ridurre la dipendenza dall'economia tradizionale e vivere in modo più sostenibile
|
||||||
|
.benefit-item
|
||||||
|
span.benefit-icon 📱
|
||||||
|
span.benefit-text Creare annunci di ciò che offri o cerchi direttamente dall'app
|
||||||
|
.benefit-item
|
||||||
|
span.benefit-icon 🎯
|
||||||
|
span.benefit-text Partecipare a mercatini ed eventi locali organizzati dalla tua comunità
|
||||||
|
|
||||||
|
//- Valori
|
||||||
|
.values-section
|
||||||
|
h3 ⭐ I Valori della Comunità RISO
|
||||||
|
.value-item
|
||||||
|
span.benefit-icon 🤝
|
||||||
|
| <strong>Comunità:</strong> Creiamo legami autentici tra persone
|
||||||
|
.value-item
|
||||||
|
span.benefit-icon ✅
|
||||||
|
| <strong>Fiducia:</strong> Base del nostro sistema di scambio
|
||||||
|
.value-item
|
||||||
|
span.benefit-icon 🚫
|
||||||
|
| <strong>Non speculativo:</strong> I RIS non hanno valore in sé, si esauriscono negli scambi
|
||||||
|
.value-item
|
||||||
|
span.benefit-icon 🌍
|
||||||
|
| <strong>Sostenibilità:</strong> Promuoviamo stili di vita sani e naturali
|
||||||
|
.value-item
|
||||||
|
span.benefit-icon 👁️
|
||||||
|
| <strong>Trasparenza:</strong> Tutte le transazioni in RIS sono visibili alla comunità
|
||||||
|
|
||||||
|
//- Info RIS
|
||||||
|
.riso-info
|
||||||
|
h3 💡 Come funzionano i RIS?
|
||||||
|
p
|
||||||
|
| • Non esiste una banca centrale che li crea<br>
|
||||||
|
| • Ogni utente parte da <strong>0 RIS</strong><br>
|
||||||
|
| • Quando ricevi vai in positivo (+), quando spendi vai in negativo (-)<br>
|
||||||
|
| • I facilitatori locali ti abilitano all'uso in base a conoscenza e fiducia<br>
|
||||||
|
| • I circuiti provinciali hanno bilancio sempre a zero (sostenibilità garantita!)
|
||||||
|
|
||||||
|
//- CTA
|
||||||
|
.cta-section
|
||||||
|
.cta-title Unisciti alla Comunità RISO 🍚💚☀️
|
||||||
|
a.cta-button(href=linkRegistrazione target="_blank") Registrati Ora
|
||||||
|
|
||||||
|
//- Info pratica
|
||||||
|
.info-box
|
||||||
|
p
|
||||||
|
| ✓ <strong>Piattaforma Libera e Gratuita</strong><br>
|
||||||
|
| ✓ <strong>Registrazione ad invito</strong> · Necessario username Telegram<br>
|
||||||
|
| ✓ <strong>App web installabile</strong> · Non serve store, installa da browser
|
||||||
|
|
||||||
|
//- Telegram
|
||||||
|
.telegram-box
|
||||||
|
p
|
||||||
|
| 📲 <strong>Unisciti al gruppo Telegram della tua provincia!</strong><br>
|
||||||
|
| Cerca "<strong>Progetto RISO</strong>" su Telegram e trova il gruppo nel messaggio fissato.<br>
|
||||||
|
| Qui organizziamo incontri reali e mercatini. 🍚
|
||||||
|
|
||||||
|
//- Link utile
|
||||||
|
.link-box
|
||||||
|
p 📚 Vuoi saperne di più sul sistema RIS?
|
||||||
|
a(href="https://sicrenacc.info/" target="_blank") Leggi il libro Si.cre.na.C.C →
|
||||||
|
|
||||||
|
//- Footer
|
||||||
|
.email-footer
|
||||||
|
.divider
|
||||||
|
p Hai ricevuto questa email perché #{usernameInvitante || 'un membro della comunità'} ti ha invitato su #{nomeapp}
|
||||||
|
p(style="margin-top: 12px; font-size: 12px;")
|
||||||
|
| © #{new Date().getFullYear()} #{nomeapp} - Rete Italiana Scambi Orizzontali
|
||||||
|
p(style="margin-top: 8px; font-size: 11px; color: #999;")
|
||||||
|
| Se non sei interessato, puoi semplicemente ignorare questa email.
|
||||||
|
p(style="margin-top: 12px; font-size: 12px;")
|
||||||
|
| 🍚 Comunità · Fiducia · Scambi Solidali · Sostenibilità
|
||||||
1
emails/invitaamico/it/subject.pug
Executable file
1
emails/invitaamico/it/subject.pug
Executable file
@@ -0,0 +1 @@
|
|||||||
|
=`${usernameInvitante} ti ha invitato su ${nomeapp}`
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
p Ciao #{name},<br>Grazie per aver inviato la tua richiesta di adesione come Sostenitore di Arcadei !
|
|
||||||
p Cordiali Saluti<br>Arcadei
|
|
||||||
|
|
||||||
style(type="text/css").
|
|
||||||
html, body {
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
p {
|
|
||||||
font-size: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.divbtn {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-lg {
|
|
||||||
padding: 5px;
|
|
||||||
margin: 5px;
|
|
||||||
font-size: 26px;
|
|
||||||
cursor: pointer;
|
|
||||||
color: white;
|
|
||||||
background: #027be3 !important;
|
|
||||||
border-radius: 28px;
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
=`Richiesta di Adesione ad Arcadei (${name} ${surname})`
|
|
||||||
@@ -1,37 +1,309 @@
|
|||||||
p Benvenuto #{name} nel portale di #{nomeapp}!
|
doctype html
|
||||||
p I tuoi dati di accesso da ricordare sono:
|
html(lang="it")
|
||||||
span Username:
|
head
|
||||||
strong #{username}<br>
|
meta(charset="UTF-8")
|
||||||
span hai dimenticato la Password? :
|
meta(name="viewport" content="width=device-width, initial-scale=1.0")
|
||||||
strong <a href=#{forgetpwd} target="_blank">Trovala qui</a><br>
|
style(type="text/css").
|
||||||
span Email:
|
* {
|
||||||
strong #{emailto}<br>
|
|
||||||
p Per confermare la registrazione clicca sul bottone, oppure su questo link: #{strlinkreg}
|
|
||||||
div.divbtn <a href=#{strlinkreg} target="_blank">
|
|
||||||
button.btn.btn-lg Verifica Registrazione</a>
|
|
||||||
|
|
||||||
p Potrai cosi' accedere al sito digitando i tuoi dati di accesso.
|
|
||||||
|
|
||||||
|
|
||||||
style(type="text/css").
|
|
||||||
html, body {
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
.divbtn {
|
body {
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
padding: 20px;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
.header-logo {
|
||||||
|
width: 80px;
|
||||||
|
height: auto;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
display: block;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.email-container {
|
||||||
|
max-width: 600px;
|
||||||
|
margin: 0 auto;
|
||||||
|
background: white;
|
||||||
|
border-radius: 12px;
|
||||||
|
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.email-header {
|
||||||
|
background: linear-gradient(135deg, #027be3 0%, #0056b3 100%);
|
||||||
|
color: white;
|
||||||
|
padding: 40px 24px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.email-header h1 {
|
||||||
|
margin: 0 0 8px 0;
|
||||||
|
font-size: 28px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.email-header p {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 16px;
|
||||||
|
opacity: 0.95;
|
||||||
|
}
|
||||||
|
|
||||||
|
.welcome-icon {
|
||||||
|
font-size: 48px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.email-body {
|
||||||
|
padding: 20px 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.intro-text {
|
||||||
|
font-size: 16px;
|
||||||
|
color: #333;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 1.7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.credentials-box {
|
||||||
|
background: #f8f9fa;
|
||||||
|
border-left: 4px solid #027be3;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 12px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.credentials-title {
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #555;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.credential-row {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
padding: 6px 0;
|
||||||
|
border-bottom: 1px solid #e0e0e0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-lg {
|
.credential-row:last-child {
|
||||||
padding: 5px;
|
border-bottom: none;
|
||||||
margin: 5px;
|
padding-bottom: 0;
|
||||||
font-size: 26px;
|
}
|
||||||
cursor: pointer;
|
|
||||||
|
.credential-label {
|
||||||
|
font-weight: 600;
|
||||||
|
color: #666;
|
||||||
|
min-width: 120px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.credential-value {
|
||||||
|
color: #1a1a1a;
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: 500;
|
||||||
|
flex: 1;
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
.credential-value a {
|
||||||
|
color: #027be3;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.credential-value a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cta-section {
|
||||||
|
text-align: center;
|
||||||
|
margin: 16px 0;
|
||||||
|
padding: 16px 0;
|
||||||
|
border-top: 1px solid #e0e0e0;
|
||||||
|
border-bottom: 1px solid #e0e0e0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cta-title {
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #1a1a1a;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cta-button {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 16px 48px;
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 600;
|
||||||
color: white;
|
color: white;
|
||||||
background: #027be3 !important;
|
background: linear-gradient(135deg, #027be3 0%, #0056b3 100%);
|
||||||
border-radius: 28px;
|
border-radius: 50px;
|
||||||
|
text-decoration: none;
|
||||||
|
box-shadow: 0 4px 12px rgba(2, 123, 227, 0.3);
|
||||||
|
transition: transform 0.2s, box-shadow 0.2s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.cta-button:hover {
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 6px 16px rgba(2, 123, 227, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.alternative-link {
|
||||||
|
margin-top: 16px;
|
||||||
|
font-size: 13px;
|
||||||
|
color: #777;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alternative-link a {
|
||||||
|
color: #027be3;
|
||||||
|
text-decoration: none;
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-box {
|
||||||
|
background: #e3f2fd;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 10px;
|
||||||
|
margin-top: 12px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-box p {
|
||||||
|
margin: 0;
|
||||||
|
color: #1565c0;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.email-footer {
|
||||||
|
padding: 16px 12px;
|
||||||
|
text-align: center;
|
||||||
|
background: #f8f9fa;
|
||||||
|
color: #777;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.email-footer p {
|
||||||
|
margin: 4px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.divider {
|
||||||
|
height: 1px;
|
||||||
|
background: linear-gradient(to right, transparent, #e0e0e0, transparent);
|
||||||
|
margin: 24px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media only screen and (max-width: 600px) {
|
||||||
|
body {
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.email-header {
|
||||||
|
padding: 16px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.email-header h1 {
|
||||||
|
font-size: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.email-body {
|
||||||
|
padding: 16px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.credentials-box {
|
||||||
|
padding: 20px 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.credential-row {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.credential-label {
|
||||||
|
margin-bottom: 4px;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.credential-value {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cta-button {
|
||||||
|
padding: 14px 32px;
|
||||||
|
font-size: 16px;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 300px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
body
|
||||||
|
.email-container
|
||||||
|
.email-header
|
||||||
|
- var baseimg = baseurl + '/';
|
||||||
|
img.header-logo(src=baseimg+"images/logo.png" alt=nomeapp || 'Logo')
|
||||||
|
h1 Benvenuto #{name ? ', ' + name : username}
|
||||||
|
| su #{nomeapp || 'la nostra piattaforma'}!
|
||||||
|
|
||||||
|
.email-body
|
||||||
|
.intro-text
|
||||||
|
| Verifica il tuo indirizzo email cliccando sul pulsante qui sotto.
|
||||||
|
.cta-section
|
||||||
|
.cta-title 🔐 1. Verifica il tuo account
|
||||||
|
|
||||||
|
if strlinkreg
|
||||||
|
a.cta-button(href=strlinkreg target="_blank") Verifica Registrazione
|
||||||
|
|
||||||
|
.alternative-link
|
||||||
|
| Oppure copia e incolla questo link nel tuo browser:
|
||||||
|
br
|
||||||
|
a(href=strlinkreg target="_blank") #{strlinkreg}
|
||||||
|
|
||||||
|
.info-box
|
||||||
|
p
|
||||||
|
strong ✓ Dopo la verifica
|
||||||
|
| potrai accedere alla piattaforma utilizzando le tue credenziali e
|
||||||
|
strong completare il tuo profilo.
|
||||||
|
|
||||||
|
.cta-section
|
||||||
|
.cta-title 🔐 2. Per accedere alla piattaforma #{nomeapp}
|
||||||
|
|
||||||
|
if strlinksito
|
||||||
|
a.cta-button(href=strlinksito target="_blank") Accedi a #{nomeapp}
|
||||||
|
|
||||||
|
.credentials-box
|
||||||
|
.credentials-title 📋 I tuoi dati di accesso
|
||||||
|
|
||||||
|
if username
|
||||||
|
.credential-row
|
||||||
|
.credential-label Username:
|
||||||
|
.credential-value #{username}
|
||||||
|
|
||||||
|
if emailto
|
||||||
|
.credential-row
|
||||||
|
.credential-label Email:
|
||||||
|
.credential-value #{emailto}
|
||||||
|
|
||||||
|
if forgetpwd
|
||||||
|
.credential-row
|
||||||
|
.credential-label Password:
|
||||||
|
.credential-value
|
||||||
|
| (la password che hai inserito)
|
||||||
|
br
|
||||||
|
a(href=forgetpwd target="_blank") Hai dimenticato la password?
|
||||||
|
|
||||||
|
|
||||||
|
.email-footer
|
||||||
|
.divider
|
||||||
|
p Hai ricevuto questa email perché ti sei registrato su #{nomeapp || 'la nostra piattaforma'}
|
||||||
|
p(style="margin-top: 12px; font-size: 12px;")
|
||||||
|
| © #{new Date().getFullYear()} #{nomeapp || ''}.
|
||||||
|
p(style="margin-top: 8px; font-size: 11px; color: #999;")
|
||||||
|
| Se non hai richiesto questa registrazione, ignora questa email.
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
p Welcome #{name} to the portal #{nomeapp}!
|
|
||||||
p Your access data to remember are:
|
|
||||||
span Username:
|
|
||||||
strong #{username}<br>
|
|
||||||
span Forgot your Password? :
|
|
||||||
strong <a href=#{forgetpwd} target="_blank">Find it here</a><br>
|
|
||||||
span Email:
|
|
||||||
strong #{emailto}<br>
|
|
||||||
p To confirm the registration click on the button:
|
|
||||||
div.divbtn <a href=#{strlinkreg} target="_blank">
|
|
||||||
button.btn.btn-lg Verify Registration</a>
|
|
||||||
|
|
||||||
|
|
||||||
p You can then access your personal area by clicking on LOGIN and filling in all the STEPS required by :
|
|
||||||
strong "Step by Step Guide" !<br>
|
|
||||||
|
|
||||||
|
|
||||||
style(type="text/css").
|
|
||||||
html, body {
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.divbtn {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-lg {
|
|
||||||
padding: 5px;
|
|
||||||
margin: 5px;
|
|
||||||
font-size: 26px;
|
|
||||||
cursor: pointer;
|
|
||||||
color: white;
|
|
||||||
background: #027be3 !important;
|
|
||||||
border-radius: 28px;
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
=`Confirm Registration to ${nomeapp}`
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
p ¡Bienvenido #{name} al portal #{nomeapp}!
|
|
||||||
p Sus datos de acceso a recordar son:
|
|
||||||
Nombre Usuario:
|
|
||||||
strong #{username}<br>
|
|
||||||
span ¿Olvidaste tu contraseña? :
|
|
||||||
strong <a href=#{forgetpwd} target="_blank">Encuéntrelo aquí</a><br>
|
|
||||||
span Email:
|
|
||||||
strong #{emailto}<br>
|
|
||||||
p Para confirmar el registro haz clic en el botón, o aquì #{strlinkreg}:
|
|
||||||
div.divbtn <a href=#{strlinkreg} target="_blank">
|
|
||||||
button.btn.btn-lg Verificar registro</a>
|
|
||||||
|
|
||||||
p A continuación, puede acceder a su área personal haciendo clic en INICIAR SESIÓN y rellenando todos los PASOS requeridos por :
|
|
||||||
strong "Guía paso a paso"!<br>
|
|
||||||
|
|
||||||
|
|
||||||
style(type="text/css").
|
|
||||||
html, body {
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.divbtn {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-lg {
|
|
||||||
padding: 5px;
|
|
||||||
margin: 5px;
|
|
||||||
font-size: 26px;
|
|
||||||
cursor: pointer;
|
|
||||||
color: white;
|
|
||||||
background: #027be3 !important;
|
|
||||||
border-radius: 28px;
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
=`Confirmar registro a ${nomeapp}`
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
p Bienvenue #{name} sur le portail de #{nomeapp} !
|
|
||||||
p Vos identifiants de connexion à retenir sont :
|
|
||||||
span Username:
|
|
||||||
strong #{username}<br>
|
|
||||||
span avez-vous oublié votre mot de passe ? :
|
|
||||||
strong <a href=#{forgetpwd} target="_blank">Essayez ici</a><br>
|
|
||||||
span Email:
|
|
||||||
strong #{emailto}<br>
|
|
||||||
p Cliquez sur le bouton pour confirmer votre inscription ou cliquez ici #{strlinkreg}:
|
|
||||||
div.divbtn <a href=#{strlinkreg} target="_blank">
|
|
||||||
button.btn.btn-lg Vérifier l'enregistrement</a>
|
|
||||||
|
|
||||||
p Vous pouvez ensuite accéder à votre espace personnel en entrant votre nom d'utilisateur et votre mot de passe et en cliquant sur
|
|
||||||
strong ENTREZ<br>
|
|
||||||
|
|
||||||
p Donc, une fois que vous avez vérifié votre inscription, connectez-vous au site et
|
|
||||||
strong COMPLÉTER TOUTES LES ÉTAPES
|
|
||||||
de la portée du "Guide pas-à-pas" via ce lien:<br>
|
|
||||||
span <a href=#{strlinksito} target="_blank">#{strlinksito}</a>
|
|
||||||
|
|
||||||
|
|
||||||
style(type="text/css").
|
|
||||||
html, body {
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.divbtn {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-lg {
|
|
||||||
padding: 5px;
|
|
||||||
margin: 5px;
|
|
||||||
font-size: 26px;
|
|
||||||
cursor: pointer;
|
|
||||||
color: white;
|
|
||||||
background: #027be3 !important;
|
|
||||||
border-radius: 28px;
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
=`Confirmer l'inscription à ${nomeapp}`
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
p Benvenuto #{name} nel portale di #{nomeapp}!
|
|
||||||
p I tuoi dati di accesso da ricordare sono:
|
|
||||||
span Username:
|
|
||||||
strong #{username}<br>
|
|
||||||
span hai dimenticato la Password? :
|
|
||||||
strong <a href=#{forgetpwd} target="_blank">Trovala qui</a><br>
|
|
||||||
span Email:
|
|
||||||
strong #{emailto}<br>
|
|
||||||
p Per confermare la registrazione clicca sul bottone, oppure <a href=#{strlinkreg} target="_blank">CLICCA QUI</a>
|
|
||||||
div.divbtn <a href=#{strlinkreg} target="_blank">
|
|
||||||
button.btn.btn-lg Verifica Registrazione</a>
|
|
||||||
|
|
||||||
p Potrai cosi' accedere alla tua area personale inserendo lo username e la password e cliccando su
|
|
||||||
strong ACCEDI <br>
|
|
||||||
|
|
||||||
p Pertanto una volta Verificata la Registrazione, accedi al sito e
|
|
||||||
strong COMPLETA TUTTI I PASSI
|
|
||||||
span della "Guida Passo Passo" tramite questo Link:<br>
|
|
||||||
span <a href=#{strlinksito} target="_blank">#{strlinksito}</a>
|
|
||||||
|
|
||||||
|
|
||||||
style(type="text/css").
|
|
||||||
html, body {
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.divbtn {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-lg {
|
|
||||||
padding: 5px;
|
|
||||||
margin: 5px;
|
|
||||||
font-size: 26px;
|
|
||||||
cursor: pointer;
|
|
||||||
color: white;
|
|
||||||
background: #027be3 !important;
|
|
||||||
border-radius: 28px;
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
=`Confermare la Registrazione a ${nomeapp}`
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
p Bem-vindo #{name} ao portal de #{nomeapp}!
|
|
||||||
p Os seus dados de login a lembrar são:
|
|
||||||
span Username:
|
|
||||||
strong #{username}<br>
|
|
||||||
span você esqueceu sua senha? :
|
|
||||||
strong <a href=##{forgetpwd} target="_blank">Encontre-o aqui</a>>br>
|
|
||||||
span Email:
|
|
||||||
strong #{emailto}<br>
|
|
||||||
p Clique no botão para confirmar o seu registo ou clique aqui #{strlinkreg}:
|
|
||||||
div.divbtn <a href=#{strlinkreg} target="_blank">
|
|
||||||
button.btn.btn-lg Verificação de registro</a>
|
|
||||||
|
|
||||||
p Você pode então acessar sua área pessoal digitando seu nome de usuário e senha e clicando em
|
|
||||||
strong ENTRAR <br>
|
|
||||||
|
|
||||||
p Então, uma vez verificada a sua inscrição, inicie a sessão no site e
|
|
||||||
strong COMPLETA TODOS OS PASSOS
|
|
||||||
span do "Guia Passo a Passo" através deste link:<br>
|
|
||||||
span <a href=#{strlinksito} target="_blank">#{strlinksito}</a>
|
|
||||||
|
|
||||||
|
|
||||||
style(type="text/css").
|
|
||||||
html, body {
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.divbtn {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-lg {
|
|
||||||
padding: 5px;
|
|
||||||
margin: 5px;
|
|
||||||
font-size: 26px;
|
|
||||||
cursor: pointer;
|
|
||||||
color: white;
|
|
||||||
background: #027be3 !important;
|
|
||||||
border-radius: 28px;
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
=`Confirme o registo em ${nomeapp}`
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
p Dobrodošli #{name} na portalu #{nomeapp}!
|
|
||||||
p Vaši podatki za dostop so:
|
|
||||||
span Username:
|
|
||||||
strong #{username}<br>
|
|
||||||
span ste pozabili geslo? :
|
|
||||||
strong <a href=#{forgetpwd} target="_blank">Poiščite tukaj</a><br>
|
|
||||||
span Email:
|
|
||||||
strong #{emailto}<br>
|
|
||||||
p Za potrditev registracije kliknite na gumb ali kliknite tukaj: #{strlinkreg}
|
|
||||||
div.divbtn <a href=#{strlinkreg} target="_blank">
|
|
||||||
button.btn.btn-lg Preveri registracijo</a>
|
|
||||||
|
|
||||||
p Tako boste lahko dostopali do svojega osebnega območja, tako da vnesete uporabniško ime in geslo in kliknete
|
|
||||||
strong PRIJAVA <br>
|
|
||||||
|
|
||||||
|
|
||||||
p Potem ko je registracija preverjena, obiščite spletno mesto in
|
|
||||||
strong IZPOLNITE VSE KORAKE
|
|
||||||
span "Vodnika po korakih" prek te povezave:<br>
|
|
||||||
span <a href=#{strlinksito} target="_blank">#{strlinksito}</a>
|
|
||||||
|
|
||||||
|
|
||||||
style(type="text/css").
|
|
||||||
html, body {
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.divbtn {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-lg {
|
|
||||||
padding: 5px;
|
|
||||||
margin: 5px;
|
|
||||||
font-size: 26px;
|
|
||||||
cursor: pointer;
|
|
||||||
color: white;
|
|
||||||
background: #027be3 !important;
|
|
||||||
border-radius: 28px;
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
=`Potrdi registracijo za ${nomeapp}`
|
|
||||||
22
filelog.txt
22
filelog.txt
@@ -36,3 +36,25 @@ Sab 11/10 ORE 19:36: USER [surya1977]: ciao
|
|||||||
Sab 11/10 ORE 19:38: USER [surya1977]: ciao
|
Sab 11/10 ORE 19:38: USER [surya1977]: ciao
|
||||||
|
|
||||||
Lun 27/10 ORE 13:35: USER [surya1977]: ciao
|
Lun 27/10 ORE 13:35: USER [surya1977]: ciao
|
||||||
|
|
||||||
|
Gio 06/11 ORE 11:46: USER [SuryaSecondo]: ciao
|
||||||
|
|
||||||
|
Gio 06/11 ORE 11:46: USER [SuryaSecondo]: chi sono
|
||||||
|
|
||||||
|
Gio 06/11 ORE 11:47: USER [SuryaSecondo]: exitontelegram
|
||||||
|
|
||||||
|
Sab 08/11 ORE 20:24: USER [SuryaSecondo]: ciao
|
||||||
|
|
||||||
|
Sab 08/11 ORE 20:24: USER [surya1977]: /start 4b989bfb3d9af38551a8459ddf4a902c82e12017600c29bc050cc56fb835a881
|
||||||
|
|
||||||
|
Sab 08/11 ORE 20:24: USER [SuryaSecondo]: /start 4b989bfb3d9af38551a8459ddf4a902c82e12017600c29bc050cc56fb835a881
|
||||||
|
|
||||||
|
Sab 08/11 ORE 20:24: USER [SuryaSecondo]: /start 4b989bfb3d9af38551a8459ddf4a902c82e12017600c29bc050cc56fb835a881
|
||||||
|
|
||||||
|
Sab 08/11 ORE 21:42: USER [surya4]: ciao
|
||||||
|
|
||||||
|
Dom 09/11 ORE 17:57: USER [surya4]: ciao
|
||||||
|
|
||||||
|
Dom 09/11 ORE 18:36: USER [surya4]: ciao
|
||||||
|
|
||||||
|
Dom 09/11 ORE 18:43: USER [surya4]: ciao
|
||||||
|
|||||||
@@ -840,3 +840,19 @@ Lun 07/07 ORE 10:50: 🤖: Da Sùrya undefined (surya1977):
|
|||||||
✅ provatest7 è stato Ammesso correttamente (da surya1977)!
|
✅ provatest7 è stato Ammesso correttamente (da surya1977)!
|
||||||
Gio 09/10 ORE 20:45: 🤖: Da Sùrya undefined (surya1977):
|
Gio 09/10 ORE 20:45: 🤖: Da Sùrya undefined (surya1977):
|
||||||
✅ prova123 è stato Ammesso correttamente (da surya1977)!
|
✅ prova123 è stato Ammesso correttamente (da surya1977)!
|
||||||
|
Gio 06/11 ORE 11:47: 🤖: Da Surya Ar (SuryaSecondo):
|
||||||
|
exitontelegram
|
||||||
|
Gio 06/11 ORE 11:51: 🤖: Da Sùrya undefined (surya1977):
|
||||||
|
✅ SuryaArena è stato Ammesso correttamente (da surya1977)!
|
||||||
|
Gio 06/11 ORE 20:38: 🤖: Da Sùrya undefined (surya1977):
|
||||||
|
✅ surya3 è stato Ammesso correttamente (da surya1977)!
|
||||||
|
Gio 06/11 ORE 22:50: 🤖: Da Sùrya undefined (surya1977):
|
||||||
|
✅ surya4 è stato Ammesso correttamente (da surya1977)!
|
||||||
|
Sab 08/11 ORE 20:24: 🤖: Da Sùrya (surya1977):
|
||||||
|
/start 4b989bfb3d9af38551a8459ddf4a902c82e12017600c29bc050cc56fb835a881
|
||||||
|
Sab 08/11 ORE 20:24: 🤖: Da Surya Ar (SuryaSecondo):
|
||||||
|
/start 4b989bfb3d9af38551a8459ddf4a902c82e12017600c29bc050cc56fb835a881
|
||||||
|
Sab 08/11 ORE 20:24: 🤖: Da Surya Ar (SuryaSecondo):
|
||||||
|
/start 4b989bfb3d9af38551a8459ddf4a902c82e12017600c29bc050cc56fb835a881
|
||||||
|
Dom 09/11 ORE 18:36: 🤖: Da Sùrya undefined (surya1977):
|
||||||
|
✅ surya4 è stato Ammesso correttamente (da surya1977)!
|
||||||
10
package.json
10
package.json
@@ -2,15 +2,15 @@
|
|||||||
"name": "freeplanet-serverside",
|
"name": "freeplanet-serverside",
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"description": "freeplanet serverside",
|
"description": "freeplanet serverside",
|
||||||
"main": "server/server.js",
|
"main": "server.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "node src/server/server.js",
|
"start": "node src/server.js",
|
||||||
"dev": "NODE_ENV=development nodemon src/server/server.js",
|
"dev": "NODE_ENV=development nodemon src/server.js",
|
||||||
"build": "gulp build",
|
"build": "gulp build",
|
||||||
"watch": "gulp watch",
|
"watch": "gulp watch",
|
||||||
"test": "export NODE_ENV=development || SET NODE_ENV=development && mocha src/server/**/*.test.js",
|
"test": "export NODE_ENV=development || SET NODE_ENV=development && mocha src/server/**/*.test.js",
|
||||||
"start:prod": "NODE_ENV=production node src/server/server.js",
|
"start:prod": "NODE_ENV=production node src/server.js",
|
||||||
"starttest": "NODE_ENV=test node src/server/server.js",
|
"starttest": "NODE_ENV=test node src/server.js",
|
||||||
"test-watch": "nodemon --exec 'npm test'"
|
"test-watch": "nodemon --exec 'npm test'"
|
||||||
},
|
},
|
||||||
"author": "Surya",
|
"author": "Surya",
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ var file = `.env.${node_env}`;
|
|||||||
|
|
||||||
// GLOBALI (Uguali per TUTTI)
|
// GLOBALI (Uguali per TUTTI)
|
||||||
process.env.LINKVERIF_REG = '/vreg';
|
process.env.LINKVERIF_REG = '/vreg';
|
||||||
|
process.env.LINK_INVITO_A_REG = '/invitetoreg';
|
||||||
process.env.LINK_REQUEST_NEWPASSWORD = '/requestnewpwd';
|
process.env.LINK_REQUEST_NEWPASSWORD = '/requestnewpwd';
|
||||||
process.env.ADD_NEW_SITE = '/addNewSite';
|
process.env.ADD_NEW_SITE = '/addNewSite';
|
||||||
process.env.LINK_UPDATE_PASSWORD = '/updatepassword';
|
process.env.LINK_UPDATE_PASSWORD = '/updatepassword';
|
||||||
294
src/controllers/telegram.controller.js
Normal file
294
src/controllers/telegram.controller.js
Normal file
@@ -0,0 +1,294 @@
|
|||||||
|
// telegram.controller.js
|
||||||
|
const crypto = require('crypto');
|
||||||
|
const axios = require('axios');
|
||||||
|
const { User } = require('../models/user');
|
||||||
|
|
||||||
|
// Configurazione
|
||||||
|
const TELEGRAM_BOT_TOKEN = process.env.TELEGRAM_BOT_TOKEN;
|
||||||
|
const TELEGRAM_API_URL = `https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}`;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Genera un token di verifica univoco
|
||||||
|
*/
|
||||||
|
exports.generateVerificationToken = async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { username, idapp } = req.body;
|
||||||
|
|
||||||
|
if (!username) {
|
||||||
|
return res.status(400).json({ error: 'Username richiesto' });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verifica che l'utente esista
|
||||||
|
const user = await User.findOne({ idapp, username });
|
||||||
|
if (!user) {
|
||||||
|
return res.status(404).json({ error: 'Utente non trovato' });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verifica se già verificato
|
||||||
|
if (user.profile?.username_telegram && user.profile?.teleg_id) {
|
||||||
|
return res.status(400).json({ error: 'Account Telegram già collegato' });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Genera token univoco
|
||||||
|
const token = crypto.randomBytes(32).toString('hex');
|
||||||
|
|
||||||
|
// Salva SOLO sul database (non serve la Map in-memory!)
|
||||||
|
await User.updateOne(
|
||||||
|
{ _id: user._id },
|
||||||
|
{
|
||||||
|
$set: {
|
||||||
|
'profile.telegram_verification_token': token,
|
||||||
|
'profile.telegram_verification_expires': new Date(Date.now() + 20 * 60 * 1000),
|
||||||
|
'profile.telegram_verified': false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
res.json({ token });
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Errore generazione token:', error);
|
||||||
|
return res.status(500).json({ error: 'Errore del server' });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Controlla se la verifica è stata completata
|
||||||
|
*/
|
||||||
|
exports.checkVerification = async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { token } = req.query;
|
||||||
|
|
||||||
|
if (!token) {
|
||||||
|
return res.status(400).json({ error: 'Token richiesto' });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cerca l'utente con questo token DIRETTAMENTE sul DB
|
||||||
|
const user = await User.findOne({
|
||||||
|
'profile.telegram_verification_token': token,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
return res.status(404).json({ error: 'Token non valido', verified: false });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verifica se è scaduto
|
||||||
|
const now = new Date();
|
||||||
|
if (now > user.profile.telegram_verification_expires) {
|
||||||
|
// Pulisci il token scaduto
|
||||||
|
await User.updateOne(
|
||||||
|
{ _id: user._id },
|
||||||
|
{
|
||||||
|
$unset: {
|
||||||
|
'profile.telegram_verification_token': '',
|
||||||
|
'profile.telegram_verification_expires': '',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return res.status(410).json({ error: 'Token scaduto', verified: false });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Controlla se è stato verificato
|
||||||
|
const verified = !!(user.profile?.teleg_id && user.profile?.username_telegram);
|
||||||
|
|
||||||
|
res.json({
|
||||||
|
verified: verified,
|
||||||
|
username_telegram: user.profile?.username_telegram || null,
|
||||||
|
teleg_id: user.profile?.teleg_id || null,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Errore verifica token:', error);
|
||||||
|
return res.status(500).json({ error: 'Errore del server' });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Webhook del bot Telegram
|
||||||
|
* Gestisce i messaggi /start con il token
|
||||||
|
*/
|
||||||
|
exports.telegramWebhook = async (req, res) => {
|
||||||
|
try {
|
||||||
|
const update = req.body;
|
||||||
|
|
||||||
|
// Gestisci solo messaggi con /start
|
||||||
|
if (update.message && update.message.text && update.message.text.startsWith('/start')) {
|
||||||
|
const chatId = update.message.chat.id;
|
||||||
|
const userId = update.message.from.id;
|
||||||
|
const username = update.message.from.username;
|
||||||
|
const firstName = update.message.from.first_name;
|
||||||
|
|
||||||
|
// Estrai il token dal comando /start
|
||||||
|
const parts = update.message.text.split(' ');
|
||||||
|
const token = parts[1];
|
||||||
|
|
||||||
|
if (!token) {
|
||||||
|
await sendTelegramMessage(
|
||||||
|
chatId,
|
||||||
|
"⚠️ Link di verifica non valido. Richiedi un nuovo link dall'applicazione."
|
||||||
|
);
|
||||||
|
return res.sendStatus(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cerca l'utente con questo token
|
||||||
|
const user = await User.findOne({
|
||||||
|
'profile.telegram_verification_token': token,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
await sendTelegramMessage(
|
||||||
|
chatId,
|
||||||
|
"❌ Token non valido o scaduto. Richiedi un nuovo link dall'applicazione."
|
||||||
|
);
|
||||||
|
return res.sendStatus(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verifica scadenza
|
||||||
|
const now = new Date();
|
||||||
|
if (now > user.profile.telegram_verification_expires) {
|
||||||
|
await User.updateOne(
|
||||||
|
{ _id: user._id },
|
||||||
|
{
|
||||||
|
$unset: {
|
||||||
|
'profile.telegram_verification_token': '',
|
||||||
|
'profile.telegram_verification_expires': '',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
await sendTelegramMessage(
|
||||||
|
chatId,
|
||||||
|
"⏰ Il token è scaduto. Richiedi un nuovo link dall'applicazione."
|
||||||
|
);
|
||||||
|
return res.sendStatus(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verifica se già collegato
|
||||||
|
if (user.profile?.teleg_id && user.profile?.username_telegram) {
|
||||||
|
await sendTelegramMessage(chatId, '✅ Questo account è già stato verificato!');
|
||||||
|
return res.sendStatus(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Salva i dati Telegram e rimuovi il token
|
||||||
|
await User.updateOne(
|
||||||
|
{ _id: user._id },
|
||||||
|
{
|
||||||
|
$set: {
|
||||||
|
'profile.teleg_id': userId.toString(),
|
||||||
|
'profile.username_telegram': username || firstName,
|
||||||
|
},
|
||||||
|
$unset: {
|
||||||
|
'profile.telegram_verification_token': '',
|
||||||
|
'profile.telegram_verification_expires': '',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// Invia messaggio di conferma
|
||||||
|
await sendTelegramMessage(
|
||||||
|
chatId,
|
||||||
|
`✅ Account verificato con successo!\n\n` +
|
||||||
|
`Il tuo Telegram è stato collegato a: ${user.username}\n\n` +
|
||||||
|
`Puoi ora tornare all'applicazione.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
res.sendStatus(200);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Errore webhook Telegram:', error);
|
||||||
|
res.sendStatus(500);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Funzione helper per inviare messaggi Telegram
|
||||||
|
*/
|
||||||
|
async function sendTelegramMessage(chatId, text) {
|
||||||
|
try {
|
||||||
|
await axios.post(`${TELEGRAM_API_URL}/sendMessage`, {
|
||||||
|
chat_id: chatId,
|
||||||
|
text: text,
|
||||||
|
parse_mode: 'HTML',
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Errore invio messaggio Telegram:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configura il webhook di Telegram (da eseguire una volta)
|
||||||
|
*/
|
||||||
|
exports.setupWebhook = async (req, res) => {
|
||||||
|
try {
|
||||||
|
/*const webhookUrl = `${process.env.APP_URL}/api/telegram/webhook`;
|
||||||
|
|
||||||
|
const response = await axios.post(`${TELEGRAM_API_URL}/setWebhook`, {
|
||||||
|
url: webhookUrl,
|
||||||
|
allowed_updates: ['message'],
|
||||||
|
});
|
||||||
|
|
||||||
|
res.json({
|
||||||
|
success: true,
|
||||||
|
message: 'Webhook configurato',
|
||||||
|
data: response.data,
|
||||||
|
});*/
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Errore setup webhook:', error);
|
||||||
|
return res.status(500).json({ error: 'Errore configurazione webhook' });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rimuovi collegamento Telegram
|
||||||
|
*/
|
||||||
|
exports.unlinkTelegram = async (req, res) => {
|
||||||
|
try {
|
||||||
|
const userId = req.user.id; // Assumi autenticazione middleware
|
||||||
|
|
||||||
|
await User.updateOne(
|
||||||
|
{ _id: userId },
|
||||||
|
{
|
||||||
|
$unset: {
|
||||||
|
'profile.teleg_id': '',
|
||||||
|
'profile.username_telegram': '',
|
||||||
|
'profile.telegram_verification_token': '',
|
||||||
|
'profile.telegram_verification_expires': '',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
res.json({ success: true, message: 'Telegram scollegato' });
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Errore unlink Telegram:', error);
|
||||||
|
return res.status(500).json({ error: 'Errore del server' });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Salta la verifica Telegram
|
||||||
|
*/
|
||||||
|
exports.skipTelegramVerification = async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { idapp } = req.body;
|
||||||
|
|
||||||
|
const user = await User.findOne({ idapp });
|
||||||
|
if (!user) {
|
||||||
|
return res.status(404).json({ error: 'Utente non trovato' });
|
||||||
|
}
|
||||||
|
|
||||||
|
await User.updateOne(
|
||||||
|
{ _id: user._id },
|
||||||
|
{
|
||||||
|
$set: {
|
||||||
|
'profile.telegram_verification_skipped': true,
|
||||||
|
},
|
||||||
|
$unset: {
|
||||||
|
'profile.telegram_verification_token': '',
|
||||||
|
'profile.telegram_verification_expires': '',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
res.json({ success: true, message: 'Verifica Telegram saltata' });
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Errore skip verifica:', error);
|
||||||
|
return res.status(500).json({ error: 'Errore del server' });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Can't render this file because it is too large.
|
@@ -118,6 +118,7 @@
|
|||||||
"SET_ATTEND": "%s ha detto che Parteciperà all'evento: %s",
|
"SET_ATTEND": "%s ha detto che Parteciperà all'evento: %s",
|
||||||
"SET_ATTEND_OTHERS": "%s e altre %s persone hanno detto che Parteciperanno all'evento: %s",
|
"SET_ATTEND_OTHERS": "%s e altre %s persone hanno detto che Parteciperanno all'evento: %s",
|
||||||
"DATEDAYONLY": "%s dalle %s alle %s",
|
"DATEDAYONLY": "%s dalle %s alle %s",
|
||||||
|
"DATE_1DAY": "%s dalle %s",
|
||||||
"DATE_2DAYS": "%s dalle %s fino a %s alle %s",
|
"DATE_2DAYS": "%s dalle %s fino a %s alle %s",
|
||||||
"SENDMSG_ENTRA_IN_RISO_ITALIA": "Ciao %s!<br>%s che appartiene al <em>%s</em> vuole inviarti dei RIS. Per poterli ricevere dovete entrambi utilizzare il <strong>Circuito RIS Italia</strong>.",
|
"SENDMSG_ENTRA_IN_RISO_ITALIA": "Ciao %s!<br>%s che appartiene al <em>%s</em> vuole inviarti dei RIS. Per poterli ricevere dovete entrambi utilizzare il <strong>Circuito RIS Italia</strong>.",
|
||||||
"CLICCA_QUI": "CLICCA QUI",
|
"CLICCA_QUI": "CLICCA QUI",
|
||||||
124
src/middleware/authenticate.js
Executable file
124
src/middleware/authenticate.js
Executable file
@@ -0,0 +1,124 @@
|
|||||||
|
const server_constants = require('../tools/server_constants');
|
||||||
|
|
||||||
|
var { User } = require('../models/user');
|
||||||
|
|
||||||
|
const tools = require('../tools/general');
|
||||||
|
|
||||||
|
const auth_default = (req, res, next) => {
|
||||||
|
if (req.body.keyappid === process.env.KEY_APP_ID) next();
|
||||||
|
};
|
||||||
|
|
||||||
|
const authenticateMiddleware = async (req, res, next, withUser = false, lean = false, noError = false) => {
|
||||||
|
// Wrapper per res.send che logga automaticamente
|
||||||
|
const originalSend = res.send;
|
||||||
|
res.send = function (data) {
|
||||||
|
logResponse(req, res, data);
|
||||||
|
return originalSend.call(this, data);
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
const logPrefix = noError ? (withUser ? (lean ? 'WITHUSERLEAN' : 'WITHUSER') : 'NOERROR') : 'AUTH';
|
||||||
|
|
||||||
|
// Validazione token
|
||||||
|
const token = req.header('x-auth');
|
||||||
|
if (!token) {
|
||||||
|
return handleAuthFailure(req, res, next, {
|
||||||
|
code: server_constants.RIS_CODE_HTTP_INVALID_TOKEN,
|
||||||
|
message: 'TOKEN INVALIDO',
|
||||||
|
logPrefix,
|
||||||
|
noError,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recupera utente
|
||||||
|
const refreshToken = req.header('x-refrtok');
|
||||||
|
const user = await User.findByToken(token, 'auth', false, withUser, lean);
|
||||||
|
|
||||||
|
// Imposta dati richiesta
|
||||||
|
req.user = user.code === server_constants.RIS_CODE_OK ? user.user : null;
|
||||||
|
req.token = user.code === server_constants.RIS_CODE_OK ? token : null;
|
||||||
|
req.refreshToken = refreshToken;
|
||||||
|
req.code = user.code;
|
||||||
|
req.statuscode2 = null;
|
||||||
|
|
||||||
|
// Gestione token scaduto
|
||||||
|
if (user.code === server_constants.RIS_CODE_HTTP_FORBIDDEN_TOKEN_EXPIRED) {
|
||||||
|
return handleAuthFailure(req, res, next, {
|
||||||
|
code: server_constants.RIS_CODE_HTTP_FORBIDDEN_TOKEN_EXPIRED,
|
||||||
|
message: 'TOKEN SCADUTO',
|
||||||
|
logPrefix,
|
||||||
|
noError,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gestione altri errori di autenticazione
|
||||||
|
if (user.code !== server_constants.RIS_CODE_OK) {
|
||||||
|
return handleAuthFailure(req, res, next, {
|
||||||
|
code: user.code,
|
||||||
|
message: 'AUTENTICAZIONE FALLITA',
|
||||||
|
logPrefix,
|
||||||
|
noError,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
next();
|
||||||
|
} catch (e) {
|
||||||
|
console.error('❌ Errore nel middleware di autenticazione:', e);
|
||||||
|
return handleAuthFailure(req, res, next, {
|
||||||
|
code: server_constants.RIS_CODE_HTTP_INVALID_TOKEN,
|
||||||
|
message: 'ERRORE INTERNO',
|
||||||
|
logPrefix: 'ERROR',
|
||||||
|
noError,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Funzione helper per gestire i fallimenti di autenticazione
|
||||||
|
function handleAuthFailure(req, res, next, { code, message, logPrefix, noError }) {
|
||||||
|
req.user = null;
|
||||||
|
req.token = null;
|
||||||
|
req.code = code;
|
||||||
|
|
||||||
|
if (noError) {
|
||||||
|
req.statuscode2 = code;
|
||||||
|
console.log(` ## ${logPrefix} - ${message} (noError mode, continuing) ⚠️`);
|
||||||
|
return next();
|
||||||
|
} else {
|
||||||
|
console.log(` ## SEND RES ${logPrefix} - ${message} ❌`);
|
||||||
|
return res.status(code).send();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Funzione per loggare le risposte
|
||||||
|
function logResponse(req, res, data) {
|
||||||
|
const statusCode = res.statusCode;
|
||||||
|
const method = req.method;
|
||||||
|
const url = req.originalUrl || req.url;
|
||||||
|
const userId = req.user?._id || req.user?.id || 'N/A';
|
||||||
|
|
||||||
|
const emoji = statusCode >= 200 && statusCode < 300 ? '✅' : statusCode >= 400 && statusCode < 500 ? '⚠️' : '❌';
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
`${emoji} [${method}] ${url} | Status: ${statusCode} | User: ${userId} | Data: ${
|
||||||
|
data ? JSON.stringify(data).substring(0, 100) : 'empty'
|
||||||
|
}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const authenticate = (req, res, next) => authenticateMiddleware(req, res, next);
|
||||||
|
const authenticate_withUser = (req, res, next) => authenticateMiddleware(req, res, next, true);
|
||||||
|
const authenticate_withUserLean = (req, res, next) => authenticateMiddleware(req, res, next, true, true);
|
||||||
|
const authenticate_noerror = (req, res, next) => authenticateMiddleware(req, res, next, false, false, true);
|
||||||
|
const authenticate_noerror_WithUser = (req, res, next) => authenticateMiddleware(req, res, next, true, false, true);
|
||||||
|
const authenticate_noerror_WithUserLean = (req, res, next) => {
|
||||||
|
return authenticateMiddleware(req, res, next, true, true, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
authenticate,
|
||||||
|
authenticate_noerror,
|
||||||
|
auth_default,
|
||||||
|
authenticate_withUser,
|
||||||
|
authenticate_noerror_WithUser,
|
||||||
|
authenticate_noerror_WithUserLean,
|
||||||
|
};
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user