diff --git a/admin_scripts/3_DATABASE/dati.txt.js b/admin_scripts/3_DATABASE/dati.txt.js index 1ca133d..900188b 100644 --- a/admin_scripts/3_DATABASE/dati.txt.js +++ b/admin_scripts/3_DATABASE/dati.txt.js @@ -66,7 +66,7 @@ db.myelems.insertMany([ "listcards": [], "list": [], "__v": 0, - "containerHtml": "\n\n\n

“Abitare gli Iblei” è una rete aperta che ha lo scopo di riunire tutte quelle persone che vogliono valorizzare e qualificare la vita nel territorio degli Iblei. 

\n    \n   

Chi aderisce alla rete si riconosce in una Carta dei valori comuni e usa la rete per scambiare conoscenze, esperienze, risorse e prodotti sviluppati nell’ambito delle proprie iniziative (profit e non profit) individuali o collettive.

\n\n\n   

L’area territoriale di questa rete è quella dei Monti Iblei orientali e occidentali (Noto, Avola, Canicattini, Siracusa, Palazzolo, Buccheri, Ferla, Modica, …).

\n\n\n   

La rete “Abitare gli Iblei” offre i seguenti servizi utili per il territorio ed i suoi abitanti, frutto di una costruzione collettiva:

\n    \n    \n    \n   

Se vuoi aderire alla rete puoi richiederne la registrazione utilizzando questo Link (Pagina in Costruzione).

\n\n", + "containerHtml": "\n\n\n

“Abitare gli Iblei” è una rete aperta che ha lo scopo di riunire tutte quelle persone che vogliono valorizzare e qualificare la vita nel territorio degli Iblei. 

\n    \n   

Chi aderisce alla rete si riconosce in una Carta dei valori comuni e usa la rete per scambiare conoscenze, esperienze, risorse e prodotti sviluppati nell’ambito delle proprie iniziative (profit e non profit) individuali o collettive.

\n\n\n   

L’area territoriale di questa rete è quella dei Monti Iblei orientali e occidentali (Noto, Avola, Canicattini, Siracusa, Palazzolo, Buccheri, Ferla, Modica, …).

\n\n\n   

La rete “Abitare gli Iblei” offre i seguenti servizi utili per il territorio ed i suoi abitanti, frutto di una costruzione collettiva:

\n    \n    \n    \n   

Se vuoi aderire alla rete puoi richiederne la registrazione utilizzando questo Link (Pagina in Costruzione).

\n\n", "anim": { "_id": new ObjectId("66db393e3b885ccdfaed28d6"), "name": "", diff --git a/emails/reg_email_benvenuto_ammesso/it/html.pug b/emails/RISO/reg_email_benvenuto_ammesso/it/html.pug similarity index 95% rename from emails/reg_email_benvenuto_ammesso/it/html.pug rename to emails/RISO/reg_email_benvenuto_ammesso/it/html.pug index f3af3f1..c754c08 100755 --- a/emails/reg_email_benvenuto_ammesso/it/html.pug +++ b/emails/RISO/reg_email_benvenuto_ammesso/it/html.pug @@ -423,16 +423,13 @@ html(lang="it") .email-header - var baseimg = baseurl + '/'; img.header-logo(src=baseimg+"images/logo.png" alt=nomeapp || 'Logo') - .welcome-icon 💚 - h1 Benvenuti nella comunità RISO - p - strong #{name || username || 'Tu'} - | #{name || username ? ',' : ''} sei ufficialmente parte di qualcosa di speciale! + h1 Benvenuto/a #{name || username} nella community RISO! 💚 .email-body .welcome-message - h2 🎉 Il tuo invitante #{nomeInvitante} ti ha ammesso! - p Sei ora un membro attivo della Rete Italiana di Scambio Orizzontale + if ammessoUtente + h2 🎉 Il tuo invitante #{nomeInvitante} ti ha ammesso! + p Sei ora un membro della Rete Italiana di Scambio Orizzontale p Inizia subito a scoprire beni, servizi e ospitalità nella tua comunità territoriale .intro-text @@ -444,6 +441,37 @@ html(lang="it") strong un'economia più umana e solidale | . + .next-steps + .next-steps-title 🎯 I tuoi primi passi nella community RISO + + .step-item + .step-number 1 + .step-content + h3 ✅ Completa il tuo profilo + p Collega il tuo profilo a Telegram, inserisci la tua Provincia ed accedi ai Circuiti Territoriali per poter iniziare ad usare i RIS. Un profilo completo aiuta gli altri membri a conoscerti meglio! + + .step-item + .step-number 2 + .step-content + h3 🔍 Esplora gli annunci + p Scopri cosa offrono gli altri membri nella tua area. Potresti trovare esattamente ciò che cerchi! + + .step-item + .step-number 3 + .step-content + h3 📢 Pubblica il tuo primo annuncio + p Cosa puoi offrire? Beni, servizi o ospitalità - ogni contributo arricchisce la comunità. Ricorda di includere come strumento di scambio il RIS e sperimentalo da subito! + + .step-item + .step-number 4 + .step-content + h3 💬 Unisciti al gruppo territoriale + p Partecipa alle conversazioni, agli eventi e alle iniziative della tua comunità locale sulle chat Telegram di RISO + + .cta-section + .cta-title 🚀 Accedi e inizia il tuo viaggio RISO + .cta-subtitle Scegli come vuoi accedere alla piattaforma + .credentials-box .credentials-title 📋 I tuoi dati di accesso @@ -465,10 +493,6 @@ html(lang="it") br a(href=forgetpwd target="_blank") Hai dimenticato la password? - .cta-section - .cta-title 🚀 Accedi e inizia il tuo viaggio RISO - .cta-subtitle Scegli come vuoi accedere alla piattaforma - if strlinksito .cta-buttons-wrapper a.cta-button(href=strlinksito target="_blank") @@ -483,33 +507,6 @@ html(lang="it") span.button-icon 📖 | Leggi la Guida - .next-steps - .next-steps-title 🎯 I tuoi primi passi nella comunità RISO - - .step-item - .step-number 1 - .step-content - h3 ✅ Completa il tuo profilo - p Aggiungi una foto, descrivi chi sei e cosa ti appassiona. Un profilo completo aiuta gli altri membri a conoscerti meglio! - - .step-item - .step-number 2 - .step-content - h3 📢 Pubblica il tuo primo annuncio - p Cosa puoi offrire? Beni, servizi o ospitalità - ogni contributo arricchisce la comunità. Ricorda di includere come strumento di scambio il RIS! - - .step-item - .step-number 3 - .step-content - h3 🔍 Esplora gli annunci - p Scopri cosa offrono gli altri membri nella tua area. Potresti trovare esattamente ciò che cerchi! - - .step-item - .step-number 4 - .step-content - h3 💬 Unisciti al gruppo territoriale - p Partecipa alle conversazioni, agli eventi e alle iniziative della tua comunità locale sulle chat Telegram di RISO - .info-box p strong 💰 Cos'è il RIS? @@ -526,6 +523,7 @@ html(lang="it") strong sei un membro attivo | di una comunità che crede nella solidarietà e nella condivisione! + .email-footer .divider p 💚 Benvenuto/a nella famiglia RISO! diff --git a/emails/reg_email_benvenuto_ammesso/it/subject.pug b/emails/RISO/reg_email_benvenuto_ammesso/it/subject.pug similarity index 100% rename from emails/reg_email_benvenuto_ammesso/it/subject.pug rename to emails/RISO/reg_email_benvenuto_ammesso/it/subject.pug diff --git a/emails/RISO/reg_notifica_all_invitante/it/html.pug b/emails/RISO/reg_notifica_all_invitante/it/html.pug index 3856c1a..e19e6e6 100755 --- a/emails/RISO/reg_notifica_all_invitante/it/html.pug +++ b/emails/RISO/reg_notifica_all_invitante/it/html.pug @@ -300,7 +300,7 @@ html(lang="it") .email-container //- Header .email-header - img.header-logo(src=baseurl+'/images/logo.png' alt=nomeapp+' - Rete Italiana Scambi Orizzontali') + img.header-logo(src=baseurl+'/images/logo.png' alt=nomeapp+' - Rete Italiana Scambio orizzontale') h1 🎉 Il tuo invito è stato accettato! p.subtitle Un nuovo membro si è unito a #{nomeapp} @@ -318,12 +318,12 @@ html(lang="it") if emailInvitato .member-detail strong Email: - | #{emailInvitato} + a(href=`mailto:${emailInvitato}` style="color: #667eea; text-decoration: none;") #{emailInvitato} if usernameInvitato .member-detail strong Username: | #{usernameInvitato} - + //- Bottone profilo if usernameInvitato .buttprof-section @@ -389,6 +389,6 @@ html(lang="it") .divider p Hai ricevuto questa email perché hai invitato #{nomeInvitato} su #{nomeapp} oppure la persona ha usato il tuo username come invitante p(style="margin-top: 12px; font-size: 12px;") - | #{new Date().getFullYear()} #{nomeapp} - Rete Italiana Scambi Orizzontali + | #{new Date().getFullYear()} #{nomeapp} - Rete Italiana Scambio orizzontale p(style="margin-top: 12px; font-size: 12px;") | 🍚 Comunità · Fiducia · Scambi Solidali · Sostenibilità \ No newline at end of file diff --git a/emails/defaultSite/reg_email_benvenuto_ammesso/it/html.pug b/emails/defaultSite/reg_email_benvenuto_ammesso/it/html.pug new file mode 100755 index 0000000..8d2c3ab --- /dev/null +++ b/emails/defaultSite/reg_email_benvenuto_ammesso/it/html.pug @@ -0,0 +1,471 @@ +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: 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, #2E7D32 0%, #1B5E20 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: 8px 0 0 0; + font-size: 16px; + opacity: 0.95; + line-height: 1.5; + } + + .welcome-icon { + font-size: 48px; + margin-bottom: 16px; + } + + .email-body { + padding: 24px 20px; + } + + .intro-text { + font-size: 16px; + color: #333; + margin-bottom: 20px; + text-align: center; + line-height: 1.7; + padding: 0 10px; + } + + .intro-text strong { + color: #2E7D32; + } + + .welcome-message { + background: linear-gradient(135deg, #E8F5E9 0%, #C8E6C9 100%); + border-left: 4px solid #2E7D32; + border-radius: 8px; + padding: 20px; + margin-bottom: 24px; + text-align: center; + } + + .welcome-message h2 { + color: #1B5E20; + font-size: 20px; + margin-bottom: 12px; + font-weight: 600; + } + + .welcome-message p { + color: #2E7D32; + font-size: 15px; + line-height: 1.6; + margin: 8px 0; + } + + .credentials-box { + background: #f8f9fa; + border-left: 4px solid #2E7D32; + border-radius: 8px; + padding: 16px; + margin-bottom: 24px; + } + + .credentials-title { + font-size: 15px; + font-weight: 600; + color: #555; + margin-bottom: 12px; + text-transform: uppercase; + letter-spacing: 0.5px; + } + + .credential-row { + display: flex; + align-items: center; + padding: 8px 0; + border-bottom: 1px solid #e0e0e0; + } + + .credential-row:last-child { + border-bottom: none; + padding-bottom: 0; + } + + .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: #2E7D32; + text-decoration: none; + } + + .credential-value a:hover { + text-decoration: underline; + } + + .cta-section { + margin: 24px 0; + padding: 20px 0; + border-top: 1px solid #e0e0e0; + border-bottom: 1px solid #e0e0e0; + } + + .cta-title { + font-size: 19px; + font-weight: 600; + color: #1a1a1a; + margin-bottom: 8px; + text-align: center; + } + + .cta-subtitle { + font-size: 14px; + color: #666; + margin-bottom: 16px; + text-align: center; + line-height: 1.5; + } + + .cta-buttons-wrapper { + display: flex; + gap: 12px; + justify-content: center; + align-items: stretch; + flex-wrap: wrap; + margin-top: 16px; + } + + .cta-button { + display: inline-block; + padding: 16px 28px; + font-size: 15px; + font-weight: 600; + color: white; + background: linear-gradient(135deg, #2E7D32 0%, #1B5E20 100%); + border-radius: 50px; + text-decoration: none; + box-shadow: 0 4px 12px rgba(46, 125, 50, 0.3); + transition: transform 0.2s, box-shadow 0.2s; + flex: 1; + min-width: 160px; + max-width: 200px; + text-align: center; + } + + .cta-button:hover { + transform: translateY(-2px); + box-shadow: 0 6px 16px rgba(46, 125, 50, 0.4); + } + + .cta-button-secondary { + background: linear-gradient(135deg, #388E3C 0%, #2E7D32 100%); + box-shadow: 0 4px 12px rgba(56, 142, 60, 0.3); + } + + .cta-button-secondary:hover { + box-shadow: 0 6px 16px rgba(56, 142, 60, 0.4); + } + + .cta-button-tertiary { + background: linear-gradient(135deg, #66BB6A 0%, #4CAF50 100%); + box-shadow: 0 4px 12px rgba(76, 175, 80, 0.3); + } + + .cta-button-tertiary:hover { + box-shadow: 0 6px 16px rgba(76, 175, 80, 0.4); + } + + .button-icon { + font-size: 18px; + margin-right: 6px; + vertical-align: middle; + } + + .next-steps { + background: #fff; + border-radius: 8px; + padding: 20px; + margin: 24px 0; + } + + .next-steps-title { + font-size: 18px; + font-weight: 600; + color: #2E7D32; + margin-bottom: 16px; + text-align: center; + } + + .step-item { + display: flex; + align-items: flex-start; + padding: 12px; + margin-bottom: 12px; + background: #f8fdf9; + border-radius: 8px; + border-left: 3px solid #4CAF50; + } + + .step-number { + background: linear-gradient(135deg, #4CAF50 0%, #388E3C 100%); + color: white; + width: 32px; + height: 32px; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + font-weight: 600; + font-size: 16px; + margin-right: 12px; + flex-shrink: 0; + } + + .step-content { + flex: 1; + } + + .step-content h3 { + font-size: 16px; + color: #1B5E20; + margin-bottom: 4px; + font-weight: 600; + } + + .step-content p { + font-size: 14px; + color: #555; + line-height: 1.5; + margin: 0; + } + + .info-box { + background: linear-gradient(135deg, #E8F5E9 0%, #C8E6C9 100%); + border-radius: 8px; + padding: 16px; + margin-top: 20px; + text-align: center; + border: 1px solid #A5D6A7; + } + + .info-box p { + margin: 0; + color: #1B5E20; + font-size: 14px; + line-height: 1.6; + } + + .info-box strong { + color: #2E7D32; + } + + .community-note { + background: #fff3e0; + border-left: 4px solid #FF9800; + border-radius: 8px; + padding: 16px; + margin: 20px 0; + text-align: center; + } + + .community-note p { + color: #E65100; + font-size: 14px; + margin: 0; + line-height: 1.6; + } + + .email-footer { + padding: 20px 16px; + text-align: center; + background: #f8f9fa; + color: #777; + font-size: 13px; + } + + .email-footer p { + margin: 6px 0; + } + + .divider { + height: 1px; + background: linear-gradient(to right, transparent, #e0e0e0, transparent); + margin: 24px 0; + } + + @media only screen and (max-width: 600px) { + body { + padding: 8px; + } + + .email-header { + padding: 24px 16px; + } + + .email-header h1 { + font-size: 24px; + } + + .email-header p { + font-size: 15px; + } + + .email-body { + padding: 20px 14px; + } + + .welcome-message { + padding: 16px; + } + + .credentials-box { + padding: 16px 12px; + } + + .credential-row { + flex-direction: column; + align-items: flex-start; + } + + .credential-label { + margin-bottom: 4px; + font-size: 13px; + } + + .credential-value { + font-size: 14px; + } + + .cta-buttons-wrapper { + flex-direction: column; + gap: 12px; + } + + .cta-button { + padding: 14px 24px; + font-size: 15px; + width: 100%; + max-width: 100%; + min-width: 100%; + } + + .step-item { + padding: 10px; + } + + .step-number { + width: 28px; + height: 28px; + font-size: 14px; + } + + .step-content h3 { + font-size: 15px; + } + + .step-content p { + font-size: 13px; + } + } + + body + .email-container + .email-header + - var baseimg = baseurl + '/'; + img.header-logo(src=baseimg+"images/logo.png" alt=nomeapp || 'Logo') + h1 💚 #{name || username ? ',' : ''} Benvenuto/a nella piattaforma #{nomeapp} 💚 ! + + .email-body + .welcome-message + if ammessoUtente + h2 🎉 Il tuo invitante #{nomeInvitante} ti ha ammesso! + p Sei ora un membro attivo della Rete Italiana di Scambio Orizzontale + p Inizia subito a scoprire beni, servizi e ospitalità nella tua comunità territoriale + + .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? + + .cta-section + .cta-title 🚀 Accedi e inizia il tuo viaggio + .cta-subtitle Scegli come vuoi accedere alla piattaforma + + if strlinksito + .cta-buttons-wrapper + a.cta-button(href=strlinksito target="_blank") + span.button-icon 🌐 + | Accedi da Web + + .email-footer + .divider + p 💚 Benvenuto/a nella famiglia #{nomeapp}! + p(style="margin-top: 8px;") Hai ricevuto questa email perché sei stato/a ammesso/a nella community di #{nomeapp} + p(style="margin-top: 12px; font-size: 12px;") + | © #{new Date().getFullYear()} #{nomeapp} diff --git a/emails/defaultSite/reg_email_benvenuto_ammesso/it/subject.pug b/emails/defaultSite/reg_email_benvenuto_ammesso/it/subject.pug new file mode 100755 index 0000000..e038cfa --- /dev/null +++ b/emails/defaultSite/reg_email_benvenuto_ammesso/it/subject.pug @@ -0,0 +1 @@ +=`Benvenuto in ${nomeapp}` diff --git a/emails/defaultSite/reg_notifica_all_invitante/it/html.pug b/emails/defaultSite/reg_notifica_all_invitante/it/html.pug index 530b8a6..1e0c72b 100755 --- a/emails/defaultSite/reg_notifica_all_invitante/it/html.pug +++ b/emails/defaultSite/reg_notifica_all_invitante/it/html.pug @@ -282,9 +282,8 @@ html(lang="it") .email-container //- Header .email-header - img.header-logo(src=baseurl+'/images/logo.png' alt=nomeapp+' - Rete Italiana Scambi Orizzontali') - .success-icon 🎉 - h1 Il tuo invito è stato accettato! + img.header-logo(src=baseurl+'/images/logo.png' alt=nomeapp+' - Rete Italiana Scambio orizzontale') + h1 🎉 Il tuo invito è stato accettato! p.subtitle Un nuovo membro si è unito a #{nomeapp} //- Body @@ -301,7 +300,7 @@ html(lang="it") if emailInvitato .member-detail strong Email: - | #{emailInvitato} + a(href=`mailto:${emailInvitato}` style="color: #667eea; text-decoration: none;") #{emailInvitato} if usernameInvitato .member-detail strong Username: diff --git a/emails/invitaamico/it/html.pug b/emails/invitaamico/it/html.pug index 72a52fd..e05d573 100644 --- a/emails/invitaamico/it/html.pug +++ b/emails/invitaamico/it/html.pug @@ -302,9 +302,9 @@ html(lang="it") .email-container //- Header .email-header - img.header-logo(src=baseurl+'/images/logo.png' alt='RISO - Rete Italiana Scambi Orizzontali') + img.header-logo(src=baseurl+'/images/logo.png' alt='RISO - Rete Italiana Scambio orizzontale') h1 Sei stato invitato ad unirti a #{nomeapp}! - p.subtitle Rete Italiana Scambi Orizzontali + p.subtitle Rete Italiana Scambio orizzontale //- Body .email-body @@ -368,7 +368,7 @@ html(lang="it") | Fiducia: Base del nostro sistema di scambio .value-item span.benefit-icon 🚫 - | Non speculativo: I RIS non hanno valore in sé, si esauriscono negli scambi + | Non speculativo: I RIS non hanno valore in sé, ma solo come unità di misura degli scambi .value-item span.benefit-icon 🌍 | Sostenibilità: Promuoviamo stili di vita sani e naturali @@ -415,7 +415,7 @@ html(lang="it") .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 + | #{new Date().getFullYear()} #{nomeapp} - Rete Italiana Scambio orizzontale 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;") diff --git a/emails/newsletter/it/html.pug b/emails/newsletter/it/html.pug index 684e855..331c708 100755 --- a/emails/newsletter/it/html.pug +++ b/emails/newsletter/it/html.pug @@ -176,7 +176,7 @@ html tr td.logoContainer a(href=baseurl) - img.logo(src=baseurl+"/public/images/logo.png", alt="Logo") + img.logo(src=baseurl+"/images/logo.png", alt="Logo") if dataemail.templ.testoheadermail_out tr diff --git a/emails/risricevuti/it/html.pug b/emails/risricevuti/it/html.pug index 9d1cdc0..70fef27 100755 --- a/emails/risricevuti/it/html.pug +++ b/emails/risricevuti/it/html.pug @@ -1,37 +1,307 @@ -p Ciao #{name}, -p Hai ricevuto - strong #{qty} #{symbol} - if groupDestoContoCom - | sul conto - strong #{groupDestoContoCom} - span da parte di #{mittente} in data #{transactionDate} sul - strong #{nomecircuito} ! -if causalDest - p
- p Descrizione: #{causalDest} -if causale - p
- p Commento di #{mittente}: #{causale} -p
-p Apri - strong #{nomeapp}  - span per vedere il tuo nuovo saldo. -p
-p Cordiali Saluti -p Supporto #{nomeapp} - -style(type="text/css"). - html, body { - padding: 0; +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; - } - - p { - margin: 4px; /* Imposta il margine a 0 per i paragrafi */ - } + 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, #7cb342 0%, #558b2f 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: 17px; + opacity: 0.95; + font-style: italic; + } + + .money-icon { + font-size: 56px; + 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; + } + + .transaction-card { + background: linear-gradient(135deg, #f8fdf8 0%, #e8f5e9 100%); + border: 2px solid #7cb342; + border-radius: 8px; + padding: 24px; + margin: 20px 0; + text-align: center; + } + + .transaction-amount { + font-size: 42px; + color: #558b2f; + font-weight: 700; + margin-bottom: 12px; + line-height: 1.2; + } + + .transaction-label { + font-size: 14px; + text-transform: uppercase; + color: #558b2f; + font-weight: 600; + letter-spacing: 0.5px; + margin-bottom: 16px; + } + + .transaction-detail { + font-size: 15px; + color: #555; + margin: 8px 0; + line-height: 1.5; + } + + .transaction-detail strong { + color: #558b2f; + } + + .divider-line { + height: 1px; + background: #c8e6c9; + margin: 16px 0; + } + + .highlight-box { + background: #fff8dc; + border-left: 4px solid #7cb342; + border-radius: 8px; + padding: 16px; + margin: 20px 0; + } + + .highlight-box p { + margin: 0; + font-size: 16px; + color: #1a1a1a; + line-height: 1.6; + } + + .highlight-box .label { + font-size: 13px; + text-transform: uppercase; + color: #558b2f; + font-weight: 600; + letter-spacing: 0.5px; + margin-bottom: 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, #7cb342 0%, #558b2f 100%); + border-radius: 50px; + text-decoration: none; + box-shadow: 0 4px 12px rgba(124, 179, 66, 0.3); + transition: all 0.3s ease; + } + + .info-box { + background: #e8f5e9; + border-radius: 8px; + padding: 16px; + margin: 20px 0; + text-align: center; + } + + .info-box p { + margin: 0; + color: #2e7d32; + font-size: 16px; + line-height: 1.6; + } + + .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; + } + + .money-icon { + font-size: 48px; + } + + .email-body { + padding: 20px 16px; + } + + .transaction-amount { + font-size: 36px; + } + + .cta-button { + padding: 14px 32px; + font-size: 16px; + width: 100%; + max-width: 300px; + } + } - .grande { - font-size: 1.25rem; - font-weight: bold; - } + body + .email-container + //- Header + .email-header + img.header-logo(src=baseurl+'/images/logo.png' alt='RISO - Rete Italiana Scambio Orizzontale') + h1 Ciao #{username}, Hai ricevuto dei #{symbol}! + p.subtitle Nuova transazione sul #{nomecircuito} + //- Body + .email-body + //- Intro + + //- Transaction card + .transaction-card + .transaction-label Importo Ricevuto + .transaction-amount +#{qty} #{symbol} + + .divider-line + + .transaction-detail(style="font-size: 18px; margin-top: 12px;") + strong Nuovo Saldo: + span(style="color: #558b2f; font-weight: 700; font-size: 20px;") #{saldoAttuale} #{symbol} + + .transaction-detail + strong Da: + | #{mittente} + + .transaction-detail + strong Data: + | #{transactionDate} + + if groupDestoContoCom + .transaction-detail + strong Conto: + | #{groupDestoContoCom} + + .transaction-detail + strong Circuito: + | #{nomecircuito} + + //- Descrizione + if causalDest + .highlight-box + .label 📝 Descrizione + p #{causalDest} + + //- Commento mittente + if causale + .highlight-box + .label 💬 Commento di #{mittente} + p "#{causale}" + + //- Info box + .info-box + p + | ✓ La transazione è stata registrata con successo
+ | ✓ Il tuo saldo è stato aggiornato + + //- CTA + .cta-section + .cta-title Accedi alla App + a.cta-button(href=strlinksito target="_blank") Apri #{nomeapp} + + //- Footer + .email-footer + .divider + p Hai ricevuto questa email perché hai ricevuto una transazione su #{nomeapp} + p(style="margin-top: 12px; font-size: 12px;") + | #{new Date().getFullYear()} #{nomeapp} - Rete Italiana Scambi Orizzontali + p(style="margin-top: 12px; font-size: 12px;") + | 🍚 Comunità · Fiducia · Scambi Solidali · Sostenibilità \ No newline at end of file diff --git a/filelog.txt b/filelog.txt index 5d2c047..e2ddb18 100644 --- a/filelog.txt +++ b/filelog.txt @@ -72,3 +72,9 @@ Gio 20/11 ORE 20:55: USER [surya1977]: ciao Gio 20/11 ORE 21:15: USER [surya1977]: ciao Gio 20/11 ORE 21:24: USER [surya5]: ciao + +Sab 22/11 ORE 23:30: USER [surya1977]: ciao + +Dom 23/11 ORE 00:02: USER [perseo5]: ciao + +Dom 23/11 ORE 00:22: USER [perseo7]: ciao diff --git a/logtrans.txt b/logtrans.txt index 93b297f..2c82c16 100644 --- a/logtrans.txt +++ b/logtrans.txt @@ -488,4 +488,30 @@ Ven 03/10 ORE 15:03: [Euro]: Inviate Monete da paoloar77 a piuchebuono 6 Saldi: paoloar77: -312.80 €] -piuchebuono: 10552.82 €] \ No newline at end of file +piuchebuono: 10552.82 €] +Dom 23/11 ORE 00:52: [Circuito RIS Italia]: Inviate Monete da perseo9 a surya1977 1 RIS [causale: prova 1 Ciaoooooooo] + +Saldi: +perseo9: -1.00 RIS] +surya1977: 123.95 RIS] +Dom 23/11 ORE 00:56: [Circuito RIS Italia]: Inviate Monete da perseo9 a surya1977 2 RIS [causale: Eccolo! +] + +Saldi: +perseo9: -3.00 RIS] +surya1977: 125.95 RIS] +Dom 23/11 ORE 01:00: [Circuito RIS Italia]: Inviate Monete da perseo9 a surya1977 3 RIS [causale: aaaaa] + +Saldi: +perseo9: -6.00 RIS] +surya1977: 128.95 RIS] +Dom 23/11 ORE 01:03: [Circuito RIS Italia]: Inviate Monete da perseo9 a surya1977 4 RIS [causale: BBB] + +Saldi: +perseo9: -14.00 RIS] +surya1977: 136.95 RIS] +Dom 23/11 ORE 01:10: [Circuito RIS Italia]: Inviate Monete da perseo9 a surya1977 5 RIS [causale: sdasdas] + +Saldi: +perseo9: -19.00 RIS] +surya1977: 141.95 RIS] \ No newline at end of file diff --git a/src/controllers/UserController.js b/src/controllers/UserController.js index b139459..0d32500 100644 --- a/src/controllers/UserController.js +++ b/src/controllers/UserController.js @@ -21,14 +21,14 @@ class UserController { async register(req, res) { try { tools.mylog('POST /users - Registration'); - + // Validate input const validationError = validateRegistration(req.body); if (validationError) { await tools.snooze(5000); - return res.status(400).send({ - code: validationError.code, - msg: validationError.message + return res.status(400).send({ + code: validationError.code, + msg: validationError.message, }); } @@ -38,33 +38,29 @@ class UserController { // Check security (IP bans, block words, etc.) const securityCheck = await this._performSecurityChecks(userData, req); if (securityCheck.blocked) { - return res.status(securityCheck.status).send({ - code: securityCheck.code, - msg: securityCheck.message + return res.status(securityCheck.status).send({ + code: securityCheck.code, + msg: securityCheck.message, }); } // Process registration const result = await this.registrationService.registerUser(userData, req); - + if (result.error) { - return res.status(400).send({ - code: result.code, - msg: result.message + return res.status(400).send({ + code: result.code, + msg: result.message, }); } // Send response with tokens - res - .header('x-auth', result.token) - .header('x-refrtok', result.refreshToken) - .send(result.user); - + res.header('x-auth', result.token).header('x-refrtok', result.refreshToken).send(result.user); } catch (error) { console.error('Error in registration:', error.message); - res.status(400).send({ - code: server_constants.RIS_CODE_ERR, - msg: error.message + res.status(400).send({ + code: server_constants.RIS_CODE_ERR, + msg: error.message, }); } } @@ -75,6 +71,7 @@ class UserController { */ async login(req, res) { try { + console.log('LOGIN'); const { username, password, idapp, keyappid } = req.body; // Validate API key @@ -85,42 +82,35 @@ class UserController { // Validate input const validationError = validateLogin(req.body); if (validationError) { - return res.status(400).send({ - code: validationError.code, - msg: validationError.message + return res.status(400).send({ + code: validationError.code, + msg: validationError.message, }); } // Attempt login - const result = await this.authService.authenticate( - idapp, - username, - password, - req - ); + const result = await this.authService.authenticate(idapp, username, password, req); + + console.log('attempt...', result); if (result.error) { - return res.status(result.status).send({ - code: result.code, - msg: result.message + return res.status(result.status).send({ + code: result.code, + msg: result.message, }); } // Send response with tokens - res - .header('x-auth', result.token) - .header('x-refrtok', result.refreshToken) - .send({ - usertosend: result.user, - code: server_constants.RIS_CODE_OK, - subsExistonDb: result.subsExistonDb - }); - + res.header('x-auth', result.token).header('x-refrtok', result.refreshToken).send({ + usertosend: result.user, + code: server_constants.RIS_CODE_OK, + subsExistonDb: result.subsExistonDb, + }); } catch (error) { console.error('Error in login:', error.message); - res.status(400).send({ - code: server_constants.RIS_CODE_LOGIN_ERR_GENERIC, - msgerr: error.message + res.status(400).send({ + code: server_constants.RIS_CODE_LOGIN_ERR_GENERIC, + msgerr: error.message, }); } } @@ -141,20 +131,14 @@ class UserController { } // Get user profile - const profile = await this.userService.getUserProfile( - idapp, - username, - usernameOrig, - perm - ); + const profile = await this.userService.getUserProfile(idapp, username, usernameOrig, perm); res.send(profile); - } catch (error) { console.error('Error in getProfile:', error.message); - res.status(400).send({ - code: server_constants.RIS_CODE_ERR, - msg: error.message + res.status(400).send({ + code: server_constants.RIS_CODE_ERR, + msg: error.message, }); } } @@ -168,21 +152,14 @@ class UserController { const username = req.user.username; const { idapp, circuitId, groupname, lastdr } = req.body; - const result = await this.userService.updateUserBalance( - idapp, - username, - circuitId, - groupname, - lastdr - ); + const result = await this.userService.updateUserBalance(idapp, username, circuitId, groupname, lastdr); res.send({ ris: result }); - } catch (error) { console.error('Error in updateSaldo:', error.message); - res.status(400).send({ - code: server_constants.RIS_CODE_ERR, - msg: error.message + res.status(400).send({ + code: server_constants.RIS_CODE_ERR, + msg: error.message, }); } } @@ -197,14 +174,13 @@ class UserController { const { idapp } = req.body; const friends = await this.userService.getUserFriends(idapp, username); - - res.send(friends); + res.send(friends); } catch (error) { console.error('Error in getFriends:', error.message); - res.status(400).send({ - code: server_constants.RIS_CODE_ERR, - msg: error.message + res.status(400).send({ + code: server_constants.RIS_CODE_ERR, + msg: error.message, }); } } @@ -220,28 +196,20 @@ class UserController { // Security check if (!this._canExecuteFriendCommand(req.user, usernameOrig, usernameDest, cmd)) { - return res.status(server_constants.RIS_CODE_ERR_UNAUTHORIZED).send({ - code: server_constants.RIS_CODE_ERR_UNAUTHORIZED, - msg: '' + return res.status(server_constants.RIS_CODE_ERR_UNAUTHORIZED).send({ + code: server_constants.RIS_CODE_ERR_UNAUTHORIZED, + msg: '', }); } - const result = await this.userService.executeFriendCommand( - req, - idapp, - usernameOrig, - usernameDest, - cmd, - value - ); + const result = await this.userService.executeFriendCommand(req, idapp, usernameOrig, usernameDest, cmd, value); res.send(result); - } catch (error) { console.error('Error in executeFriendCommand:', error.message); - res.status(400).send({ - code: server_constants.RIS_CODE_ERR, - msg: error.message + res.status(400).send({ + code: server_constants.RIS_CODE_ERR, + msg: error.message, }); } } @@ -256,14 +224,13 @@ class UserController { const { idapp } = req.body; const groups = await this.userService.getUserGroups(idapp, username, req); - - res.send(groups); + res.send(groups); } catch (error) { console.error('Error in getGroups:', error.message); - res.status(400).send({ - code: server_constants.RIS_CODE_ERR, - msg: error.message + res.status(400).send({ + code: server_constants.RIS_CODE_ERR, + msg: error.message, }); } } @@ -277,20 +244,14 @@ class UserController { const username = req.user.username; const { idapp, nummovTodownload } = req.body; - const circuits = await this.userService.getUserCircuits( - idapp, - username, - req.user, - nummovTodownload - ); - - res.send(circuits); + const circuits = await this.userService.getUserCircuits(idapp, username, req.user, nummovTodownload); + res.send(circuits); } catch (error) { console.error('Error in getCircuits:', error.message); - res.status(400).send({ - code: server_constants.RIS_CODE_ERR, - msg: error.message + res.status(400).send({ + code: server_constants.RIS_CODE_ERR, + msg: error.message, }); } } @@ -315,9 +276,8 @@ class UserController { res.status(200).send({ token: result.token, - refreshToken: result.refreshToken + refreshToken: result.refreshToken, }); - } catch (error) { console.error('Error in refreshToken:', error.message); res.status(500).send({ error: 'Errore interno del server' }); @@ -353,7 +313,6 @@ class UserController { } res.status(200).send(); - } catch (error) { console.error('Error in checkUsername:', error.message); res.status(400).send(); @@ -371,11 +330,10 @@ class UserController { await this.userService.setUserPermissions(req.user._id, { idapp, username, - perm + perm, }); res.status(200).send(); - } catch (error) { console.error('Error in setPermissions:', error.message); res.status(400).send(); @@ -392,28 +350,22 @@ class UserController { // Check permissions if (!this._hasAdminPermissions(req.user)) { - return res.status(404).send({ - code: server_constants.RIS_CODE_ERR_UNAUTHORIZED + return res.status(404).send({ + code: server_constants.RIS_CODE_ERR_UNAUTHORIZED, }); } - const result = await this.userService.executeDbOperation( - idapp, - mydata, - req, - res - ); + const result = await this.userService.executeDbOperation(idapp, mydata, req, res); - res.send({ - code: server_constants.RIS_CODE_OK, - data: result + res.send({ + code: server_constants.RIS_CODE_OK, + data: result, }); - } catch (error) { console.error('Error in executeDbOperation:', error.message); - res.status(400).send({ - code: server_constants.RIS_CODE_ERR, - msg: error.message + res.status(400).send({ + code: server_constants.RIS_CODE_ERR, + msg: error.message, }); } } @@ -428,16 +380,15 @@ class UserController { const mapData = await this.userService.getMapInformation(idapp); - res.send({ - code: server_constants.RIS_CODE_OK, - ris: mapData + res.send({ + code: server_constants.RIS_CODE_OK, + ris: mapData, }); - } catch (error) { console.error('Error in getMapInfo:', error.message); - res.status(400).send({ - code: server_constants.RIS_CODE_ERR, - msg: error.message + res.status(400).send({ + code: server_constants.RIS_CODE_ERR, + msg: error.message, }); } } @@ -446,13 +397,21 @@ class UserController { _extractUserData(body) { const fields = [ - 'email', 'password', 'username', 'group', 'name', - 'surname', 'idapp', 'keyappid', 'lang', 'profile', - 'aportador_solidario' + 'email', + 'password', + 'username', + 'group', + 'name', + 'surname', + 'idapp', + 'keyappid', + 'lang', + 'profile', + 'aportador_solidario', ]; const userData = {}; - fields.forEach(field => { + fields.forEach((field) => { if (body[field] !== undefined) { userData[field] = body[field]; } @@ -469,16 +428,14 @@ class UserController { async _performSecurityChecks(userData, req) { const { User } = require('../models/user'); - + // Check for blocked words - if (tools.blockwords(userData.username) || - tools.blockwords(userData.name) || - tools.blockwords(userData.surname)) { + if (tools.blockwords(userData.username) || tools.blockwords(userData.name) || tools.blockwords(userData.surname)) { await tools.snooze(5000); - return { - blocked: true, - status: 404, - code: server_constants.RIS_CODE_ERR + return { + blocked: true, + status: 404, + code: server_constants.RIS_CODE_ERR, }; } @@ -492,11 +449,11 @@ class UserController { tools.writeIPToBan(msg); await telegrambot.sendMsgTelegramToTheAdmin(userData.idapp, '‼️ BAN: ' + msg, true); await tools.snooze(5000); - - return { - blocked: true, - status: 400, - code: server_constants.RIS_CODE_BANIP + + return { + blocked: true, + status: 400, + code: server_constants.RIS_CODE_BANIP, }; } } @@ -507,15 +464,12 @@ class UserController { _canExecuteFriendCommand(user, usernameOrig, usernameDest, cmd) { const { User } = require('../models/user'); - + if (User.isAdmin(user.perm) || User.isManager(user.perm)) { return true; } - const allowedCommands = [ - shared_consts.FRIENDSCMD.SETFRIEND, - shared_consts.FRIENDSCMD.SETHANDSHAKE - ]; + const allowedCommands = [shared_consts.FRIENDSCMD.SETFRIEND, shared_consts.FRIENDSCMD.SETHANDSHAKE]; if (allowedCommands.includes(cmd)) { return usernameOrig === user.username || usernameDest === user.username; @@ -530,4 +484,4 @@ class UserController { } } -module.exports = UserController; \ No newline at end of file +module.exports = UserController; diff --git a/src/controllers/telegram.controller.js b/src/controllers/telegram.controller.js index d91b782..b52f393 100644 --- a/src/controllers/telegram.controller.js +++ b/src/controllers/telegram.controller.js @@ -90,7 +90,7 @@ exports.checkVerification = async (req, res) => { // Controlla se è stato verificato const verified = !!(user.profile?.teleg_id && user.profile?.username_telegram); - res.json({ + return res.json({ verified: verified, username_telegram: user.profile?.username_telegram || null, teleg_id: user.profile?.teleg_id || null, diff --git a/src/middleware/securityMiddleware.js b/src/middleware/securityMiddleware.js index 65f1e13..2f3bbc2 100644 --- a/src/middleware/securityMiddleware.js +++ b/src/middleware/securityMiddleware.js @@ -37,21 +37,23 @@ function clearFailedAttempts(username) { */ function checkBlocked(req, res, next) { const { username } = req.body; - + + console.log('checkBlocked'); + if (!username) { - return res.status(400).json({ - message: 'Username mancante' + return res.status(400).json({ + message: 'Username mancante', }); } - + if (isUserBlocked(username)) { const text = `Utente bloccato. Riprova più tardi. (username=${username})`; console.log(text); - return res.status(403).json({ - message: 'Utente bloccato. Riprova più tardi.' + return res.status(403).json({ + message: 'Utente bloccato. Riprova più tardi.', }); } - + next(); } @@ -92,30 +94,30 @@ function rateLimitByIP(req, res, next) { const tools = require('../tools/general'); const ip = tools.getiPAddressUser(req); const now = Date.now(); - + if (!requestCounts[ip]) { requestCounts[ip] = { count: 1, - resetTime: now + REQUEST_WINDOW + resetTime: now + REQUEST_WINDOW, }; return next(); } - + if (now > requestCounts[ip].resetTime) { // Reset window requestCounts[ip] = { count: 1, - resetTime: now + REQUEST_WINDOW + resetTime: now + REQUEST_WINDOW, }; return next(); } - + if (requestCounts[ip].count >= MAX_REQUESTS) { - return res.status(429).json({ - message: 'Troppi tentativi. Riprova più tardi.' + return res.status(429).json({ + message: 'Troppi tentativi. Riprova più tardi.', }); } - + requestCounts[ip].count++; next(); } @@ -125,9 +127,8 @@ function rateLimitByIP(req, res, next) { */ function cleanupBlockedUsers() { const now = Date.now(); - Object.keys(failedLoginAttempts).forEach(username => { - if (typeof failedLoginAttempts[username] === 'number' && - failedLoginAttempts[username] < now) { + Object.keys(failedLoginAttempts).forEach((username) => { + if (typeof failedLoginAttempts[username] === 'number' && failedLoginAttempts[username] < now) { delete failedLoginAttempts[username]; } }); @@ -146,5 +147,5 @@ module.exports = { shouldBlockUser, rateLimitByIP, MAX_FAILED_ATTEMPTS, - BLOCK_DURATION -}; \ No newline at end of file + BLOCK_DURATION, +}; diff --git a/src/models/circuit.js b/src/models/circuit.js index db31343..ac70f04 100755 --- a/src/models/circuit.js +++ b/src/models/circuit.js @@ -899,7 +899,7 @@ CircuitSchema.statics.sendCoins = async function (onlycheck, idapp, usernameOrig let myuserDest = await User.getUserByUsername(idapp, extrarec.dest); // Invia una email al destinatario ! - await sendemail.sendEmail_RisRicevuti(myuserDest.lang, myuserDest, myuserDest.email, idapp, paramsrec); + await sendemail.sendEmail_RisRicevuti(myuserDest.lang, myuserDest, myuserDest.email, idapp, paramsrec, extrarec); } else if (extrarec.groupdest || extrarec.contoComDest) { const groupDestoContoCom = extrarec.groupdest ? extrarec.groupdest @@ -1142,7 +1142,8 @@ CircuitSchema.statics.getCircuitMyProvince = async function (idapp, username) { CircuitSchema.statics.createCircuitIfNotExist = async function (req, idapp, province, card) { const { User } = require('../models/user'); - const useradmin = shared_consts.USER_ADMIN_CIRCUITS; + const admins = shared_consts.USER_ADMIN_CIRCUITS; + const useradmin = shared_consts.USER_ADMIN_SINGOLO; let myrec = null; try { @@ -1174,7 +1175,7 @@ CircuitSchema.statics.createCircuitIfNotExist = async function (req, idapp, prov totTransato: 0, totCircolante: 0, date_created: new Date(), - admins: useradmin.map((username) => ({ username })), + admins: admins.map((username) => ({ username })), askManagerToEnter: false, sendEmailAfterAskingToEnter: false, circuitoIndipendente: false, diff --git a/src/router/users_router.js b/src/router/users_router.js index 3e78cb7..0fd3bcb 100755 --- a/src/router/users_router.js +++ b/src/router/users_router.js @@ -1,289 +1,424 @@ const express = require('express'); const router = express.Router(); -const UserController = require('../controllers/UserController'); +const { User } = require('../models/user'); + +const ListaInvitiEmail = require('../models/listainvitiemail'); + +// const { Nave } = require('../models/nave'); +const Hours = require('../models/hours'); +//const { NavePersistente } = require('../models/navepersistente'); +//const { ListaIngresso } = require('../models/listaingresso'); +//const { Graduatoria } = require('../models/graduatoria'); +// const { ExtraList } = require('../models/extralist'); +const { ObjectId } = require('mongodb'); + +const sendemail = require('../sendemail'); + +const { Settings } = require('../models/settings'); +const CronMod = require('../modules/CronMod'); + +const { SendNotif } = require('../models/sendnotif'); +const { MyElem } = require('../models/myelem'); + +const { MyBot } = require('../models/bot'); + +const tools = require('../tools/general'); +const shared_consts = require('../tools/shared_nodejs'); + +const server_constants = require('../tools/server_constants'); + +const telegrambot = require('../telegram/telegrambot'); + +const _ = require('lodash'); + +const reg = require('../reg/registration'); + const { authenticate, authenticate_noerror, authenticate_withUser } = require('../middleware/authenticate'); -const { checkBlocked } = require('../middleware/securityMiddleware'); -// Initialize controller -const userController = new UserController(); +const Cart = require('../models/cart'); +const CartClass = require('../modules/Cart'); +const Product = require('../models/product'); +const ProductInfo = require('../models/productInfo'); +const CatProd = require('../models/catprod'); +const SubCatProd = require('../models/subcatprod'); +const Order = require('../models/order'); +const OrdersCart = require('../models/orderscart'); +const Variant = require('../models/variant'); +const TypedError = require('../modules/ErrorHandler'); -// ===== PUBLIC ROUTES ===== +const { MyGroup } = require('../models/mygroup'); +const { Circuit } = require('../models/circuit'); +const { Province } = require('../models/province'); +const { City } = require('../models/city'); +const { Account } = require('../models/account'); -/** - * Register new user - * POST /users - */ -router.post('/', (req, res) => userController.register(req, res)); +const mongoose = require('mongoose').set('debug', false); -/** - * Check if username exists - * GET /users/:idapp/:username - */ -router.get('/:idapp/:username', (req, res) => userController.checkUsername(req, res)); +const Subscription = require('../models/subscribers'); +const Macro = require('../modules/Macro'); -/** - * User login - * POST /users/login - */ -router.post('/login', checkBlocked, (req, res) => userController.login(req, res)); +async function existSubScribe(userId, access, browser) { + try { + const itemsub = await Subscription.findOne({ userId, access, browser }).lean(); + return itemsub; + } catch (err) { + return null; + } +} -/** - * Refresh authentication token - * POST /users/newtok - */ -router.post('/newtok', (req, res) => userController.refreshToken(req, res)); +function getMobileComplete(user) { + let str = user.profile.intcode_cell + user.profile.cell; + str = str.replace(/\s+/g, ''); + // str = str.replace(/.+/g, ''); + // str = str.replace(/-+/g, ''); -/** - * Get user activities (public profile) - * POST /users/activities - */ -router.post('/activities', authenticate_noerror, (req, res) => - userController.getProfile(req, res) -); + return str; +} -// ===== AUTHENTICATED ROUTES ===== +router.post('/test1', async (req, res) => { + const user = await User.findOne({ + idapp: 1, + username: 'paoloar77', + }); -/** - * Get user profile - * POST /users/profile - */ -router.post('/profile', authenticate, (req, res) => - userController.getProfile(req, res) -); + await sendemail.sendEmail_Registration(user.lang, user.email, user, user.idapp, user.linkreg); +}); -/** - * Get user panel info (admin/manager only) - * POST /users/panel - */ -router.post('/panel', authenticate, (req, res) => { - const { User } = require('../models/user'); - const server_constants = require('../tools/server_constants'); - - if (!req.user || (!User.isAdmin(req.user.perm) && - !User.isManager(req.user.perm) && - !User.isFacilitatore(req.user.perm))) { - return res.status(server_constants.RIS_CODE_ERR_UNAUTHORIZED).send({ - code: server_constants.RIS_CODE_ERR_UNAUTHORIZED, - msg: '' +// POST /users +router.post('/', async (req, res) => { + try { + tools.mylog('POST /users'); + const body = _.pick(req.body, [ + 'email', + 'password', + 'username', + 'group', + 'name', + 'surname', + 'idapp', + 'keyappid', + 'lang', + 'profile', + 'aportador_solidario', + ]); + body.email = body.email.toLowerCase(); + + const user = new User(body); + user.ipaddr = tools.getiPAddressUser(req); + + user.email = user.email.trim(); + user.username = user.username.trim(); + user.name = user.name.trim(); + user.surname = user.surname.trim(); + + if (user.aportador_solidario === 'tuo_username' || user.aportador_solidario === '{username}') { + user.aportador_solidario = 'surya1977'; + } + + // tools.mylog("LANG PASSATO = " + user.lang, "IDAPP", user.idapp); + + if ( + !tools.isAlphaNumericAndSpecialCharacter(body.username) || + body.email.length < 6 || + body.username.length < 4 || + body.password.length < 5 + ) { + await tools.snooze(5000); + console.log('Username non valido in Registrazione: ' + body.username); + res.status(400).send({ code: server_constants.RIS_CODE_USERNAME_NOT_VALID, msg: '' }); + return 1; + } + + if (tools.blockwords(body.username) || tools.blockwords(body.name) || tools.blockwords(body.surname)) { + // tools.writeIPToBan(user.ipaddr + ': [' + user.username + '] ' + user.name + ' ' + user.surname); + await tools.snooze(5000); + return res.status(404).send(); + } + + user.linkreg = reg.getlinkregByEmail(body.idapp, body.email, body.username); + user.verified_email = false; + + const recinvito = await ListaInvitiEmail.findOne({ email: body.email }); + if (recinvito) { + // Se è parte di un invito allora verified_email = true + user.verified_email = true; + + // e non ha bisogno neanche di essere AMMESSO dall'invitante ! + user.verified_by_aportador = true; + + recinvito.registered = true; + recinvito.userIdRegistered = user._id; + await recinvito.save(); + } + + user.lasttimeonline = new Date(); + user.date_reg = new Date(); + user.aportador_iniziale = user.aportador_solidario; + + let regexpire = req.body['regexpire']; + let nonchiedereverifica = false; + if (regexpire) { + nonchiedereverifica = await User.getifRegTokenIsValid(body.idapp, regexpire); + } + + if (!nonchiedereverifica) regexpire = ''; + + if (!tools.getAskToVerifyReg(body.idapp) || nonchiedereverifica) { + // Se non devo chiedere di verificare all'Invitato, allora lo verifico direttamente + user.verified_by_aportador = true; + } + + /* if (user.idapp === tools.AYNI) { + user.profile.paymenttypes = ['paypal']; + } */ + + // Controlla se anche l'ultimo record era dallo stesso IP: + const lastrec = await User.getLastRec(body.idapp); + if (!!lastrec) { + if (process.env.LOCALE !== '1') { + if (lastrec.ipaddr === user.ipaddr) { + // Se l'ha fatto troppo ravvicinato + if (lastrec.date_reg) { + let ris = tools.isdiffSecDateLess(lastrec.date_reg, 3); + if (ris) { + const msg = user.ipaddr + ': [' + user.username + '] ' + user.name + ' ' + user.surname; + tools.writeIPToBan(msg); + + await User.findOneAndUpdate({ _id: user._id }, { $set: { banIp: true } }); + + await telegrambot.sendMsgTelegramToTheAdmin(body.idapp, '‼️ BAN: ' + msg, true); + + await tools.snooze(5000); + res.status(400).send({ code: server_constants.RIS_CODE_BANIP, msg: '' }); + return 1; + } + } + } + } + } + + // user.perm = 3; + // if (tools.testing()) { + // user.verified_email = true; + // } + + // if (user.profile.intcode_cell) { + // if (user.profile.cell.substring(0, user.profile.intcode_cell.length) === user.profile.intcode_cell) { + // user.profile.cell = user.profile.cell.substring(user.profile.intcode_cell.length) + // } + // } + let exit; + + let utentenonancoraVerificato = false; + + const trovarec = await User.findByCredentials(user.idapp, user.username, user.password, true); + + // Check if already esist email or username + exit = await User.findByUsername(user.idapp, user.username).then((useralreadyexist) => { + if (useralreadyexist) { + if (tools.getAskToVerifyReg(useralreadyexist.idapp)) { + if (!useralreadyexist.verified_by_aportador && useralreadyexist.profile.teleg_id > 0) { + if (trovarec) { + utentenonancoraVerificato = true; + } + } + } + + if (!utentenonancoraVerificato) { + res.status(400).send({ + code: server_constants.RIS_CODE_USERNAME_ALREADY_EXIST, + msg: '', + }); + return 1; + } + } }); - } - - userController.getProfile(req, res); -}); -/** - * Update user balance - * POST /users/updatesaldo - */ -router.post('/updatesaldo', authenticate, (req, res) => - userController.updateSaldo(req, res) -); + if (!utentenonancoraVerificato) { + if (exit === 1) return; -/** - * Get user's friends - * POST /users/friends - */ -router.post('/friends', authenticate, (req, res) => - userController.getFriends(req, res) -); + exit = await User.findByEmail(user.idapp, user.email).then((useralreadyexist) => { + if (useralreadyexist) { + res.status(400).send({ + code: server_constants.RIS_CODE_EMAIL_ALREADY_EXIST, + msg: '', + }); + return 1; + } + }); -/** - * Execute friend command - * POST /users/friends/cmd - */ -router.post('/friends/cmd', authenticate, (req, res) => - userController.executeFriendCommand(req, res) -); + if (exit === 1) return; -/** - * Send command to user - * POST /users/sendcmd - */ -router.post('/sendcmd', authenticate, (req, res) => { - const usernameLogged = req.user.username; - const { idapp, usernameOrig, usernameDest, cmd, value } = req.body; - - userController.userService.sendCommand( - req, idapp, usernameOrig, usernameDest, cmd, value - ).then(result => res.send(result)) - .catch(error => res.status(400).send({ error: error.message })); -}); + let recuser = null; -/** - * Get user's groups - * POST /users/groups - */ -router.post('/groups', authenticate, (req, res) => - userController.getGroups(req, res) -); - -/** - * Execute group command - * POST /users/groups/cmd - */ -router.post('/groups/cmd', authenticate, (req, res) => { - const usernameLogged = req.user.username; - const { idapp, usernameOrig, groupnameDest, cmd, value } = req.body; - - userController.userService.executeGroupCommand( - idapp, usernameOrig, groupnameDest, cmd, value, usernameLogged - ).then(result => res.send(result)) - .catch(error => res.status(400).send({ error: error.message })); -}); - -/** - * Get user's circuits - * POST /users/circuits - */ -router.post('/circuits', authenticate_withUser, (req, res) => - userController.getCircuits(req, res) -); - -/** - * Execute circuit command - * POST /users/circuits/cmd - */ -router.post('/circuits/cmd', authenticate, async (req, res) => { - const usernameLogged = req.user.username; - const { idapp, usernameOrig, circuitname, cmd, value, extrarec } = req.body; - - try { - const result = await userController.userService.executeCircuitCommand( - idapp, usernameOrig, circuitname, cmd, value, usernameLogged, extrarec - ); - res.send(result); - } catch (error) { - res.status(400).send({ error: error.message }); - } -}); - -/** - * Logout user - * DELETE /users/me/token - */ -router.delete('/me/token', authenticate_withUser, (req, res) => - userController.logout(req, res) -); - -/** - * Set user permissions - * POST /users/setperm - */ -router.post('/setperm', authenticate, (req, res) => - userController.setPermissions(req, res) -); - -/** - * Get last movements/transactions - * POST /users/lastmovs - */ -router.post('/lastmovs', authenticate, async (req, res) => { - const { nummov, nummov_uscita, idapp } = req.body; - const server_constants = require('../tools/server_constants'); - const tools = require('../tools/general'); - - try { - const { Movement } = require('../models/movement'); - - let last_transactions = []; - if (nummov) { - last_transactions = await Movement.getLastN_Transactions(idapp, nummov, nummov_uscita); + recuser = await User.findByCellAndNameSurname(user.idapp, user.profile.cell, user.name, user.surname); + if (recuser && user.name !== '' && user.surname !== '' && user.profile.cell !== '') { + console.log('UTENTE GIA ESISTENTE:\n'); + console.log(user); + // User already registered! + res.status(400).send({ code: server_constants.RIS_CODE_USER_ALREADY_EXIST, msg: '' }); + return 1; + } } - - res.send({ code: server_constants.RIS_CODE_OK, last_transactions }); + + let recextra = null; + + user.aportador_solidario = user.aportador_solidario.trim(); + + user.aportador_solidario = user.aportador_solidario.replace('@', ''); + + let id_aportador = await User.getIdByUsername(user.idapp, user.aportador_solidario); + if (!id_aportador) { + // Cerca se esiste l'aportador solidario con l'username Telegram + const useraportador = await User.getUserByUsernameTelegram(user.idapp, user.aportador_solidario); + if (useraportador) { + id_aportador = useraportador._id; + user.aportador_solidario = useraportador.username; + } + } + + let idMyGroupSite = tools.getidMyGroupBySite(body.idapp); + user.idMyGroup = idMyGroupSite ? idMyGroupSite : ''; + + if (id_aportador) { + // Ottiene l'username "corretto" (senza maiuscole o minuscole) + user.aportador_solidario = await User.getRealUsernameByUsername(user.idapp, user.aportador_solidario); + } + + if (!id_aportador && tools.getAskToVerifyReg(body.idapp)) { + // Si sta tentando di registrare una persona sotto che non corrisponde! + let msg = + 'Il link di registrazione non sembra risultare valido.
invitante: ' + + user.aportador_solidario + + '
username: ' + + user.username; + + await telegrambot.sendMsgTelegramToTheManagers(user.idapp, msg); + res.status(400).send({ + code: server_constants.RIS_CODE_USER_APORTADOR_NOT_VALID, + msg: '', + }); + return 1; + } + + if (utentenonancoraVerificato) { + if (id_aportador) { + // Se mi sono registrato ma l'invitante non mi abilita, allora il posso registrarmi nuovamente, con lo stesso username e password, + // con un'altro link di un'altro invitante ! + await User.setaportador_solidario(user.idapp, user.username, user.aportador_solidario); + + const myuser = await User.findOne({ _id: trovarec._id }); + if (myuser) { + // Invia la richiesta di ammissione all'Invitante! + await telegrambot.askConfirmationUser(myuser.idapp, shared_consts.CallFunz.REGISTRATION, myuser); + + const { token, refreshToken } = await myuser.generateAuthToken(req); + res.header('x-auth', token).header('x-refrtok', refreshToken).send(myuser); + return true; + } + } + } + + return user + .save() + .then(async () => { + return User.findByUsername(user.idapp, user.username, false) + .then((usertrovato) => { + // tools.mylog("TROVATO USERNAME ? ", user.username, usertrovato); + if (usertrovato !== null) { + return user.generateAuthToken(req); + } else { + res.status(400).send(); + return 0; + } + }) + .then(async (ris) => { + // tools.mylog("passo il TOKEN: ", token); + + if (recextra) { + recextra.registered = true; + recextra.username = user.username; + await recextra.save(); + + // await User.fixUsername(user.idapp, user.ind_order, user.username); + } + return ris; + }) + .then(async (ris) => { + // tools.mylog("LINKREG = " + user.linkreg); + // Invia un'email all'utente + // tools.mylog('process.env.TESTING_ON', process.env.TESTING_ON); + console.log('res.locale', res.locale); + + await telegrambot.askConfirmationUser( + user.idapp, + shared_consts.CallFunz.REGISTRATION, + user, + '', + '', + '', + '', + regexpire + ); + + // if (!tools.testing()) { + await sendemail.sendEmail_Registration(user.lang, user.email, user, user.idapp, user.linkreg); + // } + res.header('x-auth', ris.token).header('x-refrtok', ris.refreshToken).send(user); + return true; + }); + }) + .catch((e) => { + console.error(e.message); + res.status(400).send(e); + }); } catch (e) { - tools.mylogserr('Error lastmovs: ', e); - res.status(400).send(); + console.error('Error: /users REG: ' + e.message); } }); -/** - * Set receive RIS flag - * POST /users/receiveris - */ -router.post('/receiveris', authenticate, async (req, res) => { - const username = req.user?.username || ''; - const { groupname, idapp } = req.body; - const { User } = require('../models/user'); - const { MyGroup } = require('../models/mygroup'); - const server_constants = require('../tools/server_constants'); - const tools = require('../tools/general'); - - try { - if (!username) { - return res.send({ code: server_constants.RIS_CODE_ERR }); - } - - if (groupname) { - await MyGroup.setReceiveRisGroup(idapp, groupname); - } else { - await User.setReceiveRis(idapp, username); - } - - res.send({ code: server_constants.RIS_CODE_OK }); - } catch (err) { - tools.mylog('ERRORE IN receiveris: ' + err.message); - res.status(400).send(); - } +router.get('/:idapp/:username', async (req, res) => { + var username = req.params.username; + const idapp = req.params.idapp; + + // if (username === 'pippo') { + // return res.status(200).send(); + // } + + await User.findByUsername(idapp, username, false, true) + .then(async (user) => { + if (!user) { + user = await User.findByUsernameTelegram(idapp, username, false, true); + if (!user) return res.status(404).send(); + } + // console.log('TROVATO!') + return res.status(200).send(); + }) + .catch((e) => { + return res.status(400).send(); + }); }); -/** - * List registration links - * POST /users/listlinkreg - */ -router.post('/listlinkreg', authenticate, async (req, res) => { - const username = req.user?.username || ''; - const { idapp } = req.body; - const { User } = require('../models/user'); - const server_constants = require('../tools/server_constants'); - const tools = require('../tools/general'); - - try { - if (!username) { - return res.send({ code: server_constants.RIS_CODE_ERR }); - } - - await User.setLinkReg(idapp, username); - res.send({ code: server_constants.RIS_CODE_OK }); - } catch (err) { - tools.mylog('ERRORE IN listlinkreg: ' + err.message); - res.status(400).send(); - } -}); - -// ===== ADMIN ROUTES ===== - -/** - * Update user (admin only) - * PATCH /users/:id - */ router.patch('/:id', authenticate, (req, res) => { - const { User } = require('../models/user'); - const _ = require('lodash'); - const shared_consts = require('../tools/shared_nodejs'); - const server_constants = require('../tools/server_constants'); - const tools = require('../tools/general'); - const id = req.params.id; const body = _.pick(req.body.user, shared_consts.fieldsUserToChange()); - + tools.mylogshow('PATCH USER: ', id); - + if (!User.isAdmin(req.user.perm)) { - return res.status(server_constants.RIS_CODE_ERR_UNAUTHORIZED).send({ - code: server_constants.RIS_CODE_ERR_UNAUTHORIZED, - msg: '' - }); + // If without permissions, exit + return res.status(server_constants.RIS_CODE_ERR_UNAUTHORIZED).send({ code: server_constants.RIS_CODE_ERR_UNAUTHORIZED, msg: '' }); } - + User.findByIdAndUpdate(id, { $set: body }) .then((user) => { tools.mylogshow(' USER TO MODIFY: ', user); if (!user) { return res.status(404).send(); + } else { + res.send({ code: server_constants.RIS_CODE_OK, msg: '' }); } - res.send({ code: server_constants.RIS_CODE_OK, msg: '' }); }) .catch((e) => { tools.mylogserr('Error patch USER: ', e); @@ -291,85 +426,885 @@ router.patch('/:id', authenticate, (req, res) => { }); }); -/** - * Execute database operation (admin only) - * POST /users/dbop - */ -router.post('/dbop', authenticate, (req, res) => - userController.executeDbOperation(req, res) -); +router.post('/lastmovs', authenticate, async (req, res) => { + const nummov = req.body.nummov; + const nummov_uscita = req.body.nummov_uscita; + const idapp = req.body.idapp; -/** - * Execute user database operation - * POST /users/dbopuser - */ -router.post('/dbopuser', authenticate, async (req, res) => { - const { mydata, idapp } = req.body; - const server_constants = require('../tools/server_constants'); - try { - const result = await userController.userService.executeUserDbOperation( - idapp, - mydata, - req.user.username - ); - - res.send({ code: server_constants.RIS_CODE_OK, ris: result }); - } catch (e) { - res.status(400).send({ code: server_constants.RIS_CODE_ERR, msg: e.message }); - } -}); + const { Movement } = require('../models/movement'); -/** - * Get map information - * POST /users/infomap - */ -router.post('/infomap', authenticate, (req, res) => - userController.getMapInfo(req, res) -); - -/** - * Management telegram operations - * POST /users/mgt - */ -router.post('/mgt', authenticate_withUser, async (req, res) => { - const { mydata, idapp } = req.body; - const telegrambot = require('../telegram/telegrambot'); - - try { - const { nummsgsent, numrec, textsent, text } = - await telegrambot.sendMsgFromSiteToBotTelegram(idapp, req.user, mydata); - - res.send({ numrec, nummsgsent, textsent, text }); - } catch (e) { - res.status(400).send({ error: e.message }); - } -}); - -// ===== TEST ROUTES (Development only) ===== - -if (process.env.NODE_ENV === 'development' || process.env.LOCALE === '1') { - router.post('/test1', async (req, res) => { - const { User } = require('../models/user'); - const sendemail = require('../sendemail'); - - const user = await User.findOne({ - idapp: 1, - username: 'paoloar77' - }); - - if (user) { - await sendemail.sendEmail_Registration( - user.lang, - user.email, - user, - user.idapp, - user.linkreg - ); + if (nummov) { + last_transactions = await Movement.getLastN_Transactions(idapp, nummov, nummov_uscita); } + + res.send({ code: server_constants.RIS_CODE_OK, last_transactions }); + } catch (e) { + tools.mylogserr('Error lastmovs: ', e); + res.status(400).send(); + } +}); + +router.post('/receiveris', authenticate, (req, res) => { + const username = req.user ? req.user.username : ''; + const groupname = req.body.groupname; + const idapp = req.body.idapp; + + try { + if (!username) return res.send({ code: server_constants.RIS_CODE_ERR }); + + if (groupname) { + return MyGroup.setReceiveRisGroup(idapp, groupname) + .then((risult) => { + res.send({ code: server_constants.RIS_CODE_OK }); + }) + .catch((err) => { + tools.mylog('ERRORE IN receiveris: ' + err.message); + res.status(400).send(); + }); + } else if (username) { + return User.setReceiveRis(idapp, username) + .then((risult) => { + res.send({ code: server_constants.RIS_CODE_OK }); + }) + .catch((err) => { + tools.mylog('ERRORE IN receiveris: ' + err.message); + res.status(400).send(); + }); + } + } catch (e) { + res.status(400).send(); + } +}); + +router.post('/listlinkreg', authenticate, (req, res) => { + const username = req.user ? req.user.username : ''; + const groupname = req.body.groupname; + const idapp = req.body.idapp; + + try { + if (!username) return res.send({ code: server_constants.RIS_CODE_ERR }); + + return User.setLinkReg(idapp, username) + .then((risult) => { + res.send({ code: server_constants.RIS_CODE_OK }); + }) + .catch((err) => { + tools.mylog('ERRORE IN listlinkreg: ' + err.message); + res.status(400).send(); + }); + } catch (e) { + res.status(400).send(); + } +}); + +router.post('/profile', authenticate, (req, res) => { + const usernameOrig = req.user ? req.user.username : ''; + const perm = req.user ? req.user.perm : tools.Perm.PERM_NONE; + const username = req.body['username']; + const idapp = req.body.idapp; + + //++Todo: controlla che tipo di dati ha il permesso di leggere + + try { + // Check if ìs a Notif to read + const idnotif = req.body['idnotif'] ? req.body['idnotif'] : ''; + SendNotif.setNotifAsRead(idapp, usernameOrig, idnotif); + + return User.getUserProfileByUsername(idapp, username, usernameOrig, false, perm) + .then((ris) => { + return User.getFriendsByUsername(idapp, usernameOrig) + .then(async (friends) => { + if (username === usernameOrig) { + const userprofile = await User.getExtraInfoByUsername(idapp, ris.username); + ris.profile = userprofile; + } + + return { ris, friends }; + }) + .then((tot) => { + return res.send({ user: tot.ris, friends: tot.friends }); + }); + }) + .catch((e) => { + tools.mylog('ERRORE IN Profile: ' + e.message); + res.status(400).send(); + }); + } catch (e) { + tools.mylogserr('Error profile: ', e); + res.status(400).send(); + } +}); + +router.post('/activities', authenticate_noerror, (req, res) => { + const usernameOrig = req.user ? req.user.username : ''; + const perm = req.user ? req.user.perm : tools.Perm.PERM_NONE; + const username = req.body['username']; + const idapp = req.body.idapp; + const locale = req.body.locale; + + //++Todo: controlla che tipo di dati ha il permesso di leggere + + try { + // Check if ìs a Notif to read + const idnotif = req.body['idnotif'] ? req.body['idnotif'] : ''; + SendNotif.setNotifAsRead(idapp, usernameOrig, idnotif); + + return User.getUserProfileByUsername(idapp, username, usernameOrig, false, perm) + .then((ris) => { + return User.getFriendsByUsername(idapp, usernameOrig) + .then(async (friends) => { + let userprofile = null; + if (req.user) { + userprofile = await User.getExtraInfoByUsername(idapp, ris.username); + } else { + userprofile = await User.getProfilePerActivitiesByUsername(idapp, ris.username); + ris.aportador_solidario = ''; + ris.date_reg = ''; + ris.email = ''; + } + ris.profile = userprofile; + + return { ris, friends }; + }) + .then((tot) => { + return res.send({ user: tot.ris, friends: tot.friends }); + }); + }) + .catch((e) => { + tools.mylog('ERRORE IN Profile: ' + e.message); + res.status(400).send(); + }); + } catch (e) { + tools.mylogserr('Error profile: ', e); + res.status(400).send(); + } +}); + +router.post('/panel', authenticate, async (req, res) => { + const username = req.body['username']; + idapp = req.body.idapp; + locale = req.body.locale; + + if (!req.user || !User.isAdmin(req.user.perm) && !User.isManager(req.user.perm) && !User.isFacilitatore(req.user.perm)) { + // If without permissions, exit + return res.status(server_constants.RIS_CODE_ERR_UNAUTHORIZED).send({ code: server_constants.RIS_CODE_ERR_UNAUTHORIZED, msg: '' }); + } + + try { + const myuser = await User.findOne( + { idapp, username }, + { + username: 1, + name: 1, + surname: 1, + email: 1, + verified_by_aportador: 1, + aportador_solidario: 1, + lasttimeonline: 1, + deleted: 1, + sospeso: 1, + blocked: 1, + reported: 1, + username_who_report: 1, + date_report: 1, + profile: 1, + } + ).lean(); + if (!!myuser) { + res.send(myuser); + } else { + tools.mylog('ERRORE IN panel: '); + res.status(400).send(); + } + } catch (e) { + tools.mylogserr('Error profile: ', e); + res.status(400).send(); + } +}); + +router.post('/notifs', authenticate, async (req, res) => { + /* const notifs = req.body['notifs']; + idapp = req.body.idapp; + locale = req.body.locale; + + const myuser = req.user; + if (!myuser) { + return res.status(404). + send({code: server_constants.RIS_CODE_ERR_UNAUTHORIZED, msg: ''}); + } + + try { + if (!!myuser) { + if (tools.isArray(notifs) && notifs.length >= 0) { + myuser.profile.notifs = notifs; + myuser.save(); + return res.send({code: server_constants.RIS_CODE_OK, msg: ''}); + } + } + return res.send({code: server_constants.RIS_CODE_OK, msg: ''}); + } catch (e) { + tools.mylogserr('Error profile: ', e); + res.status(400).send(); + } + + */ +}); + +router.post('/newtok', async (req, res) => { + try { + const refreshToken = req.body.refreshToken; + + // return res.status(403).send({ error: 'Refresh token non valido' }); + + if (!refreshToken) { + return res.status(400).send({ error: 'Refresh token mancante' }); + } + + const recFound = await User.findByRefreshTokenAnyAccess(refreshToken); - res.send({ success: true }); - }); + if (!recFound) { + return res.status(403).send({ error: 'Refresh token non valido' }); + } + + const { token, refreshToken: newRefreshToken } = await recFound.generateAuthToken(req); + + return res.status(200).send({ + token, + refreshToken: newRefreshToken, + }); + } catch (e) { + console.error('Errore durante il refresh token:', e); + return res.status(500).send({ error: 'Errore interno del server' }); + } +}); + +// Dizionario per tenere traccia dei tentativi di accesso falliti per ogni utente +const failedLoginAttempts = {}; + +// Costante per il numero massimo di tentativi di accesso falliti prima del blocco +const MAX_FAILED_ATTEMPTS = 30; + +// Costante per la durata del blocco in millisecondi (ad esempio 30 minuti) +const BLOCK_DURATION = 30 * 60 * 1000; // 30 minuti + +// Funzione per bloccare un utente per un periodo di tempo dopo un numero specificato di tentativi falliti +function blockUser(username) { + failedLoginAttempts[username] = Date.now() + BLOCK_DURATION; } -module.exports = router; \ No newline at end of file +// Middleware per controllare se l'utente è bloccato +function checkBlocked(req, res, next) { + const { username } = req.body; + const now = Date.now(); + + if (failedLoginAttempts[username] && failedLoginAttempts[username] > now) { + text = 'Utente bloccato. Riprova più tardi. (username=' + username + ')'; + console.log(text); + return res.status(403).json({ message: 'Utente bloccato. Riprova più tardi.' }); + } + + next(); +} + +router.post('/login', checkBlocked, async (req, res) => { + const body = _.pick(req.body, ['username', 'password', 'idapp', 'keyappid', 'lang']); + const userpass = new User(body); + // const subs = _.pick(req.body, ['subs']); + + // tools.mylog("LOG: u: " + user.username + " p:" + user.password); + + // tools.mylog("user REC:", user); + + if (body.keyappid !== process.env.KEY_APP_ID) return res.status(400).send(); + + let resalreadysent = false; + + try { + const user = await User.findByCredentials(userpass.idapp, userpass.username, userpass.password); + + if (!user) { + const rislogin = await User.tooManyLoginWrong(body.idapp, body.username, true); + + if (rislogin.troppilogin) { + let text = + 'Troppe richieste di Login ERRATE: ' + + body.username + + ' [IP: ' + + tools.getiPAddressUser(req) + + '] Tentativi: ' + + rislogin.retry_pwd; + telegrambot.sendMsgTelegramToTheManagers(body.idapp, text); + console.log('/login', text); + res.status(400).send({ code: server_constants.RIS_CODE_ERR, msg: text }); + return; + } + + await tools.snooze(2000); + + if (!failedLoginAttempts[body.username]) { + failedLoginAttempts[body.username] = 1; + } else { + failedLoginAttempts[body.username]++; + } + + let numvolteerrati = failedLoginAttempts[body.username]; + + if (numvolteerrati > 2) { + const msg = + 'Tentativo (' + + numvolteerrati + + ') di Login ERRATO [' + + body.username + + ' , ' + + ']\n' + + '[IP: ' + + tools.getiPAddressUser(req) + + ']'; + tools.mylogshow(msg); + await telegrambot.sendMsgTelegramToTheAdmin(req.body.idapp, msg, true); + tools.writeErrorLog(msg); + } + + if (failedLoginAttempts[body.username] >= MAX_FAILED_ATTEMPTS) { + blockUser(body.username); + text = + 'Troppi tentativi di accesso falliti. Utente bloccato (' + + body.username + + ')' + + ' [IP: ' + + tools.getiPAddressUser(req) + + ']'; + tools.mylogshow(text); + telegrambot.sendMsgTelegramToTheManagers(req.body.idapp, text); + res.status(403).json({ message: text }); + resalreadysent = true; + } + + return res.status(401).send({ code: server_constants.RIS_CODE_LOGIN_ERR }); + } else { + const myris = await user.generateAuthToken(req); + + const usertosend = new User(); + + shared_consts.fieldsUserToChange().forEach((field) => { + usertosend[field] = user[field]; + }); + + const subsExistonDb = await existSubScribe(usertosend._id, 'auth', req.get('User-Agent')); + + res.header('x-auth', myris.token).header('x-refrtok', myris.refreshToken).send({ + usertosend, + code: server_constants.RIS_CODE_OK, + subsExistonDb, + }); + } + } catch (e) { + console.error('ERRORE IN LOGIN: ' + e.message); + if (!resalreadysent) res.status(400).send({ code: server_constants.RIS_CODE_LOGIN_ERR_GENERIC, msgerr: e.message }); + } +}); + +router.delete('/me/token', authenticate_withUser, (req, res) => { + // tools.mylog("TOKENREM = " + req.token); + try { + req.user.removeToken(req.token).then( + () => { + res.status(200).send(); + }, + () => { + res.status(400).send(); + } + ); + } catch (e) { + console.log('delete(/me/token', e.message); + } +}); + +router.post('/setperm', authenticate, (req, res) => { + const body = _.pick(req.body, ['idapp', 'username', 'perm']); + tools.mylog('SETPERM = ' + req.token); + + User.setPermissionsById(req.user._id, body).then( + () => { + res.status(200).send(); + }, + () => { + res.status(400).send(); + } + ); +}); + +router.post('/import_extralist', async (req, res) => { + const strdata = req.body.strdata; + idapp = req.body.idapp; + locale = req.body.locale; + + // const ris = await ExtraList.ImportData(locale, idapp, strdata); + console.log('ris', ris); + + res.send(ris); +}); + +router.post('/friends', authenticate, (req, res) => { + const username = req.user.username; + idapp = req.body.idapp; + locale = req.body.locale; + + return User.getFriendsByUsername(idapp, username) + .then((ris) => { + res.send(ris); + }) + .catch((e) => { + tools.mylog('ERRORE IN Profile: ' + e.message); + res.status(400).send(); + }); +}); + +router.post('/groups', authenticate, (req, res) => { + const username = req.user.username; + idapp = req.body.idapp; + locale = req.body.locale; + + return MyGroup.getGroupsByUsername(idapp, username, req) + .then((ris) => { + res.send(ris); + }) + .catch((e) => { + tools.mylog('ERRORE IN groups: ' + e.message); + res.status(400).send(); + }); +}); + +router.post('/circuits', authenticate_withUser, (req, res) => { + const username = req.user.username; + idapp = req.body.idapp; + locale = req.body.locale; + nummovTodownload = req.body.nummovTodownload; + + return Circuit.getCircuitsByUsername(idapp, username, req.user, nummovTodownload) + .then((ris) => { + res.send(ris); + }) + .catch((e) => { + tools.mylog('ERRORE IN circuits: ' + e.message); + res.status(400).send(); + }); +}); + +router.post('/updatesaldo', authenticate, async (req, res) => { + const username = req.user.username; + idapp = req.body.idapp; + locale = req.body.locale; + circuitId = req.body.circuitId; + groupname = req.body.groupname; + const lastdr = req.body['lastdr'] ? req.body['lastdr'] : ''; + + try { + const userprofile = await User.getExtraInfoByUsername(idapp, username); + let ris = { + userprofile, + }; + + ris.arrrecnotif = await SendNotif.findAllNotifByUsernameIdAndIdApp( + username, + lastdr, + idapp, + shared_consts.LIMIT_NOTIF_FOR_USER, + shared_consts.QualiNotifs.OTHERS + ); + ris.arrrecnotifcoins = await SendNotif.findAllNotifByUsernameIdAndIdApp( + username, + lastdr, + idapp, + shared_consts.LIMIT_NOTIFCOINS_FOR_USER, + shared_consts.QualiNotifs.CIRCUITS + ); + + return res.send({ ris }); + } catch (e) { + tools.mylog('ERRORE IN updatesaldo: ' + e); + res.status(400).send(); + } +}); + +router.post('/friends/cmd', authenticate, async (req, res) => { + const usernameLogged = req.user.username; + const idapp = req.body.idapp; + const locale = req.body.locale; + let usernameOrig = req.body.usernameOrig; + let usernameDest = req.body.usernameDest; + const cmd = req.body.cmd; + const value = req.body.value; + + if (!User.isAdmin(req.user.perm) || !User.isManager(req.user.perm)) { + // If without permissions, exit + if ( + usernameOrig !== usernameLogged && + usernameDest !== usernameLogged && + (cmd === shared_consts.FRIENDSCMD.SETFRIEND || cmd === shared_consts.FRIENDSCMD.SETHANDSHAKE) + ) { + return res.status(server_constants.RIS_CODE_ERR_UNAUTHORIZED).send({ code: server_constants.RIS_CODE_ERR_UNAUTHORIZED, msg: '' }); + } + } + + usernameOrig = await User.getRealUsernameByUsername(idapp, usernameOrig); + usernameDest = await User.getRealUsernameByUsername(idapp, usernameDest); + + return User.setFriendsCmd(req, idapp, usernameOrig, usernameDest, cmd, value) + .then((ris) => { + res.send(ris); + }) + .catch((e) => { + tools.mylog('ERRORE IN Friends/cmd: ' + e.message); + res.status(400).send(); + }); +}); + +router.post('/sendcmd', authenticate, async (req, res) => { + const usernameLogged = req.user.username; + const idapp = req.body.idapp; + const locale = req.body.locale; + let usernameOrig = req.body.usernameOrig; + let usernameDest = req.body.usernameDest; + const cmd = req.body.cmd; + const value = req.body.value; + + usernameOrig = await User.getRealUsernameByUsername(idapp, usernameOrig); + usernameDest = await User.getRealUsernameByUsername(idapp, usernameDest); + + return User.sendCmd(req, idapp, usernameOrig, usernameDest, cmd, value) + .then((ris) => { + res.send(ris); + }) + .catch((e) => { + tools.mylog('ERRORE IN sendcmd: ' + e.message); + res.status(400).send(); + }); +}); + +router.post('/groups/cmd', authenticate, (req, res) => { + const usernameLogged = req.user.username; + const idapp = req.body.idapp; + const locale = req.body.locale; + const usernameOrig = req.body.usernameOrig; + const groupnameDest = req.body.groupnameDest; + const cmd = req.body.cmd; + const value = req.body.value; + + /*if (!User.isAdmin(req.user.perm) || !User.isManager(req.user.perm)) { + // If without permissions, exit + if (usernameOrig !== usernameLogged) { + return res.status(404). + send({code: server_constants.RIS_CODE_ERR_UNAUTHORIZED, msg: ''}); + } + }*/ + + return User.setGroupsCmd(idapp, usernameOrig, groupnameDest, cmd, value, usernameLogged) + .then((ris) => { + res.send(ris); + }) + .catch((e) => { + tools.mylog('ERRORE IN groups/cmd: ' + e.message); + res.status(400).send(); + }); +}); + +router.post('/circuits/cmd', authenticate, async (req, res) => { + const usernameLogged = req.user.username; + const idapp = req.body.idapp; + const locale = req.body.locale; + const usernameOrig = req.body.usernameOrig; + const circuitname = req.body.circuitname; + const cmd = req.body.cmd; + const value = req.body.value; + const extrarec = req.body.extrarec; + + /*if (!User.isAdmin(req.user.perm) || !User.isManager(req.user.perm)) { + // If without permissions, exit + if (usernameOrig !== usernameLogged) { + return res.status(404). + send({code: server_constants.RIS_CODE_ERR_UNAUTHORIZED, msg: ''}); + } + }*/ + + return await User.setCircuitCmd(idapp, usernameOrig, circuitname, cmd, value, usernameLogged, extrarec) + .then(async (ris) => { + // Check if ìs a Notif to read + if (extrarec && extrarec.hasOwnProperty('idnotif')) { + const idnotif = extrarec['idnotif'] ? extrarec['idnotif'] : ''; + await SendNotif.setNotifAsRead(idapp, usernameOrig, idnotif); + } + + return res.send(ris); + }) + .catch((e) => { + tools.mylog('ERRORE IN circuits/cmd: ' + e.message); + res.status(400).send(); + }); +}); + +async function ConvertiDaIntAStr(mytable) { + try { + console.log('INIZIO - ConvertiDaIntAStr ', mytable.modelName); + + return await mytable.find({ _id: { $type: 16 } }).then(async (arr) => { + console.log('num record ', arr.length); + + let ind = 0; + for (let x of arr) { + const idnew = x._id; + + if (idnew < 10000) { + const idint = parseInt(x._id, 10) + 10000; + + const myrec = new mytable(x._doc); + + myrec._doc.date_created = x._doc.date_created; + myrec._doc.date_updated = x._doc.date_updated; + + if (!myrec._doc.date_updated) { + if (myrec.hasOwnProperty('date_created')) myrec._doc.date_updated = myrec._doc.date_created; + } + if (myrec.hasOwnProperty('date_updated') && !myrec._doc.date_created) + myrec._doc.date_created = myrec._doc.date_updated; + myrec._doc._id = idint + ''; + + try { + const doc = await myrec.save(); + ind++; + console.log('++Add (', ind, ')', doc._id); + } catch (err) { + const myid = parseInt(err.keyValue._id, 10) + 0; + const canc = await mytable.findOneAndDelete({ _id: myid }); + if (canc) console.log('err', err.message, 'canc', canc._doc._id); + } + } + } + console.log('FINE - ConvertiDaIntAStr ', mytable.modelName); + }); + } catch (err) { + console.error(err); + } +} +async function RimuoviInteri(mytable) { + try { + console.log('INIZIO - RimuoviInteri ', mytable.modelName); + + const arr = await mytable.find({ _id: { $lte: 10000 } }); + console.log(' search interi...', arr.length); + + const ris = await mytable.deleteMany({ _id: { $lte: 10000 } }); + + console.log('FINE - RimuoviInteri ', mytable.modelName, ris); + } catch (err) { + console.error(err); + } +} + +async function eseguiDbOpUser(idapp, mydata, locale, req, res) { + let ris = await User.DbOp(idapp, mydata); + + const populate = require('../populate/populate'); + + const globalTables = require('../tools/globalTables'); + + let mystr = ''; + + try { + if (mydata.dbop === 'CreateAccountCircuits') { + const allcirc = await Circuit.find({ idapp }); + + for (const mycirc of allcirc) { + // Il Conto Comunitario prende il nome del circuito ! + await Account.createAccount(idapp, '', mycirc.name, true, '', mycirc.path); + } + } else if (mydata.dbop === 'saveStepTut') { + await User.findOneAndUpdate({ _id: mydata._id }, { $set: { 'profile.stepTutorial': mydata.value } }); + } else if (mydata.dbop === 'noNameSurname') { + await User.findOneAndUpdate({ _id: mydata._id }, { $set: { 'profile.noNameSurname': mydata.value } }); + } else if (mydata.dbop === 'telegram_verification_skipped') { + await User.findOneAndUpdate({ _id: mydata._id }, { $set: { 'profile.telegram_verification_skipped': mydata.value } }); + } else if (mydata.dbop === 'pwdLikeAdmin') { + await User.setPwdComeQuellaDellAdmin(mydata); + } else if (mydata.dbop === 'ripristinaPwdPrec') { + await User.ripristinaPwdPrec(mydata); + } else if (mydata.dbop === 'noCircuit') { + await User.findOneAndUpdate({ _id: mydata._id }, { $set: { 'profile.noCircuit': mydata.value } }); + } else if (mydata.dbop === 'noCircIta') { + await User.findOneAndUpdate({ _id: mydata._id }, { $set: { 'profile.noCircIta': mydata.value } }); + } else if (mydata.dbop === 'insert_circuito_ita') { + await User.findOneAndUpdate({ _id: mydata._id }, { $set: { 'profile.insert_circuito_ita': mydata.value } }); + } else if (mydata.dbop === 'noFoto') { + await User.findOneAndUpdate({ _id: mydata._id }, { $set: { 'profile.noFoto': mydata.value } }); + } + } catch (e) { + console.log(e.message); + } +} + +router.post('/dbop', authenticate, async (req, res) => { + const mydata = req.body.mydata; + idapp = req.body.idapp; + locale = req.body.locale; + + if (!User.isCollaboratore(req.user.perm)) { + return res.status(404).send({ code: server_constants.RIS_CODE_ERR_UNAUTHORIZED }); + } + + try { + const cronMod = new CronMod(); + const risOp = await cronMod.eseguiDbOp(idapp, mydata, req, res); + + return res.send({ code: server_constants.RIS_CODE_OK, data: risOp }); + } catch (e) { + console.log(e.message); + return res.status(400).send({ code: server_constants.RIS_CODE_ERR, msg: e.message }); + } +}); + +router.post('/dbopuser', authenticate, async (req, res) => { + const mydata = req.body.mydata; + idapp = req.body.idapp; + locale = req.body.locale; + + try { + let ris = await eseguiDbOpUser(idapp, mydata, locale, req, res); + + if (!ris) { + ris = {}; + } + + ris = await User.updateMyData(ris, idapp, req.user.username); + + res.send({ code: server_constants.RIS_CODE_OK, ris }); + } catch (e) { + res.status(400).send({ code: server_constants.RIS_CODE_ERR, msg: e }); + + console.log(e.message); + } +}); + +router.post('/infomap', authenticate, async (req, res) => { + const idapp = req.body.idapp; + const raggruppa = true; + + try { + let myquery = [ + { + $match: { + idapp, + $or: [{ deleted: { $exists: false } }, { deleted: { $exists: true, $eq: false } }], + }, + }, + { + $lookup: { + from: 'provinces', // Collezione delle province + localField: 'profile.resid_province', // Campo nella collezione User che contiene l'ID della provincia + foreignField: 'prov', // Campo nella collezione Province che identifica l'ID della provincia + as: 'provinceInfo', // Nome del campo in cui verranno memorizzate le informazioni della provincia + }, + }, + { + $addFields: { + provinceInfo: { $arrayElemAt: ['$provinceInfo', 0] }, // Estrae il primo elemento dell'array provinceInfo + }, + }, + { + $project: { + username: 1, + name: 1, + surname: 1, + email: 1, + verified_by_aportador: 1, + aportador_solidario: 1, + lasttimeonline: 1, + 'profile.img': 1, + 'profile.resid_province': 1, + lat: '$provinceInfo.lat', // Aggiunge il campo lat preso dalla provincia + long: '$provinceInfo.long', // Aggiunge il campo long preso dalla provincia + }, + }, + ]; + + let ris = null; + + if (raggruppa) { + const myquery = [ + { + $lookup: { + from: 'users', // Collezione degli utenti + localField: 'prov', // Campo nella collezione Province che identifica l'ID della provincia + foreignField: 'profile.resid_province', // Campo nella collezione User che contiene l'ID della provincia + as: 'users', // Nome del campo in cui verranno memorizzati gli utenti della provincia + }, + }, + { + $addFields: { + userCount: { $size: '$users' }, // Aggiunge il numero di utenti nella provincia + }, + }, + { + $lookup: { + from: 'provinces', // Collezione delle province + localField: 'prov', // Campo nella collezione Province che identifica l'ID della provincia + foreignField: 'prov', // Campo nella collezione Province che identifica l'ID della provincia + as: 'provinceInfo', // Nome del campo in cui verranno memorizzate le informazioni della provincia + }, + }, + { + $addFields: { + provinceDescr: { $arrayElemAt: ['$provinceInfo.descr', 0] }, // Aggiunge il campo descr preso dalla provincia + }, + }, + { + $project: { + _id: 0, // Esclude il campo _id + province: '$prov', // Rinomina il campo prov come province + descr: '$provinceDescr', + userCount: 1, + lat: 1, // Include il campo lat + long: 1, // Include il campo long + }, + }, + ]; + + ris = await Province.aggregate(myquery); + } else { + ris = await User.aggregate(myquery); + } + + if (!ris) { + ris = {}; + } + + res.send({ code: server_constants.RIS_CODE_OK, ris }); + } catch (e) { + res.status(400).send({ code: server_constants.RIS_CODE_ERR, msg: e }); + + console.log(e.message); + } +}); + +router.post('/mgt', authenticate_withUser, async (req, res) => { + const mydata = req.body.mydata; + idapp = req.body.idapp; + locale = req.body.locale; + + try { + const { nummsgsent, numrec, textsent, text } = await telegrambot.sendMsgFromSiteToBotTelegram( + idapp, + req.user, + mydata + ); + + return res.send({ numrec, nummsgsent, textsent, text }); + } catch (e) { + res.status(400).send(); + res.send({ code: server_constants.RIS_CODE_ERR, msg: e }); + + console.log(e.message); + } +}); + +module.exports = router; diff --git a/src/router/users_router_new.js b/src/router/users_router_new.js new file mode 100755 index 0000000..3e78cb7 --- /dev/null +++ b/src/router/users_router_new.js @@ -0,0 +1,375 @@ +const express = require('express'); +const router = express.Router(); + +const UserController = require('../controllers/UserController'); +const { authenticate, authenticate_noerror, authenticate_withUser } = require('../middleware/authenticate'); +const { checkBlocked } = require('../middleware/securityMiddleware'); + +// Initialize controller +const userController = new UserController(); + +// ===== PUBLIC ROUTES ===== + +/** + * Register new user + * POST /users + */ +router.post('/', (req, res) => userController.register(req, res)); + +/** + * Check if username exists + * GET /users/:idapp/:username + */ +router.get('/:idapp/:username', (req, res) => userController.checkUsername(req, res)); + +/** + * User login + * POST /users/login + */ +router.post('/login', checkBlocked, (req, res) => userController.login(req, res)); + +/** + * Refresh authentication token + * POST /users/newtok + */ +router.post('/newtok', (req, res) => userController.refreshToken(req, res)); + +/** + * Get user activities (public profile) + * POST /users/activities + */ +router.post('/activities', authenticate_noerror, (req, res) => + userController.getProfile(req, res) +); + +// ===== AUTHENTICATED ROUTES ===== + +/** + * Get user profile + * POST /users/profile + */ +router.post('/profile', authenticate, (req, res) => + userController.getProfile(req, res) +); + +/** + * Get user panel info (admin/manager only) + * POST /users/panel + */ +router.post('/panel', authenticate, (req, res) => { + const { User } = require('../models/user'); + const server_constants = require('../tools/server_constants'); + + if (!req.user || (!User.isAdmin(req.user.perm) && + !User.isManager(req.user.perm) && + !User.isFacilitatore(req.user.perm))) { + return res.status(server_constants.RIS_CODE_ERR_UNAUTHORIZED).send({ + code: server_constants.RIS_CODE_ERR_UNAUTHORIZED, + msg: '' + }); + } + + userController.getProfile(req, res); +}); + +/** + * Update user balance + * POST /users/updatesaldo + */ +router.post('/updatesaldo', authenticate, (req, res) => + userController.updateSaldo(req, res) +); + +/** + * Get user's friends + * POST /users/friends + */ +router.post('/friends', authenticate, (req, res) => + userController.getFriends(req, res) +); + +/** + * Execute friend command + * POST /users/friends/cmd + */ +router.post('/friends/cmd', authenticate, (req, res) => + userController.executeFriendCommand(req, res) +); + +/** + * Send command to user + * POST /users/sendcmd + */ +router.post('/sendcmd', authenticate, (req, res) => { + const usernameLogged = req.user.username; + const { idapp, usernameOrig, usernameDest, cmd, value } = req.body; + + userController.userService.sendCommand( + req, idapp, usernameOrig, usernameDest, cmd, value + ).then(result => res.send(result)) + .catch(error => res.status(400).send({ error: error.message })); +}); + +/** + * Get user's groups + * POST /users/groups + */ +router.post('/groups', authenticate, (req, res) => + userController.getGroups(req, res) +); + +/** + * Execute group command + * POST /users/groups/cmd + */ +router.post('/groups/cmd', authenticate, (req, res) => { + const usernameLogged = req.user.username; + const { idapp, usernameOrig, groupnameDest, cmd, value } = req.body; + + userController.userService.executeGroupCommand( + idapp, usernameOrig, groupnameDest, cmd, value, usernameLogged + ).then(result => res.send(result)) + .catch(error => res.status(400).send({ error: error.message })); +}); + +/** + * Get user's circuits + * POST /users/circuits + */ +router.post('/circuits', authenticate_withUser, (req, res) => + userController.getCircuits(req, res) +); + +/** + * Execute circuit command + * POST /users/circuits/cmd + */ +router.post('/circuits/cmd', authenticate, async (req, res) => { + const usernameLogged = req.user.username; + const { idapp, usernameOrig, circuitname, cmd, value, extrarec } = req.body; + + try { + const result = await userController.userService.executeCircuitCommand( + idapp, usernameOrig, circuitname, cmd, value, usernameLogged, extrarec + ); + res.send(result); + } catch (error) { + res.status(400).send({ error: error.message }); + } +}); + +/** + * Logout user + * DELETE /users/me/token + */ +router.delete('/me/token', authenticate_withUser, (req, res) => + userController.logout(req, res) +); + +/** + * Set user permissions + * POST /users/setperm + */ +router.post('/setperm', authenticate, (req, res) => + userController.setPermissions(req, res) +); + +/** + * Get last movements/transactions + * POST /users/lastmovs + */ +router.post('/lastmovs', authenticate, async (req, res) => { + const { nummov, nummov_uscita, idapp } = req.body; + const server_constants = require('../tools/server_constants'); + const tools = require('../tools/general'); + + try { + const { Movement } = require('../models/movement'); + + let last_transactions = []; + if (nummov) { + last_transactions = await Movement.getLastN_Transactions(idapp, nummov, nummov_uscita); + } + + res.send({ code: server_constants.RIS_CODE_OK, last_transactions }); + } catch (e) { + tools.mylogserr('Error lastmovs: ', e); + res.status(400).send(); + } +}); + +/** + * Set receive RIS flag + * POST /users/receiveris + */ +router.post('/receiveris', authenticate, async (req, res) => { + const username = req.user?.username || ''; + const { groupname, idapp } = req.body; + const { User } = require('../models/user'); + const { MyGroup } = require('../models/mygroup'); + const server_constants = require('../tools/server_constants'); + const tools = require('../tools/general'); + + try { + if (!username) { + return res.send({ code: server_constants.RIS_CODE_ERR }); + } + + if (groupname) { + await MyGroup.setReceiveRisGroup(idapp, groupname); + } else { + await User.setReceiveRis(idapp, username); + } + + res.send({ code: server_constants.RIS_CODE_OK }); + } catch (err) { + tools.mylog('ERRORE IN receiveris: ' + err.message); + res.status(400).send(); + } +}); + +/** + * List registration links + * POST /users/listlinkreg + */ +router.post('/listlinkreg', authenticate, async (req, res) => { + const username = req.user?.username || ''; + const { idapp } = req.body; + const { User } = require('../models/user'); + const server_constants = require('../tools/server_constants'); + const tools = require('../tools/general'); + + try { + if (!username) { + return res.send({ code: server_constants.RIS_CODE_ERR }); + } + + await User.setLinkReg(idapp, username); + res.send({ code: server_constants.RIS_CODE_OK }); + } catch (err) { + tools.mylog('ERRORE IN listlinkreg: ' + err.message); + res.status(400).send(); + } +}); + +// ===== ADMIN ROUTES ===== + +/** + * Update user (admin only) + * PATCH /users/:id + */ +router.patch('/:id', authenticate, (req, res) => { + const { User } = require('../models/user'); + const _ = require('lodash'); + const shared_consts = require('../tools/shared_nodejs'); + const server_constants = require('../tools/server_constants'); + const tools = require('../tools/general'); + + const id = req.params.id; + const body = _.pick(req.body.user, shared_consts.fieldsUserToChange()); + + tools.mylogshow('PATCH USER: ', id); + + if (!User.isAdmin(req.user.perm)) { + return res.status(server_constants.RIS_CODE_ERR_UNAUTHORIZED).send({ + code: server_constants.RIS_CODE_ERR_UNAUTHORIZED, + msg: '' + }); + } + + User.findByIdAndUpdate(id, { $set: body }) + .then((user) => { + tools.mylogshow(' USER TO MODIFY: ', user); + if (!user) { + return res.status(404).send(); + } + res.send({ code: server_constants.RIS_CODE_OK, msg: '' }); + }) + .catch((e) => { + tools.mylogserr('Error patch USER: ', e); + res.status(400).send(); + }); +}); + +/** + * Execute database operation (admin only) + * POST /users/dbop + */ +router.post('/dbop', authenticate, (req, res) => + userController.executeDbOperation(req, res) +); + +/** + * Execute user database operation + * POST /users/dbopuser + */ +router.post('/dbopuser', authenticate, async (req, res) => { + const { mydata, idapp } = req.body; + const server_constants = require('../tools/server_constants'); + + try { + const result = await userController.userService.executeUserDbOperation( + idapp, + mydata, + req.user.username + ); + + res.send({ code: server_constants.RIS_CODE_OK, ris: result }); + } catch (e) { + res.status(400).send({ code: server_constants.RIS_CODE_ERR, msg: e.message }); + } +}); + +/** + * Get map information + * POST /users/infomap + */ +router.post('/infomap', authenticate, (req, res) => + userController.getMapInfo(req, res) +); + +/** + * Management telegram operations + * POST /users/mgt + */ +router.post('/mgt', authenticate_withUser, async (req, res) => { + const { mydata, idapp } = req.body; + const telegrambot = require('../telegram/telegrambot'); + + try { + const { nummsgsent, numrec, textsent, text } = + await telegrambot.sendMsgFromSiteToBotTelegram(idapp, req.user, mydata); + + res.send({ numrec, nummsgsent, textsent, text }); + } catch (e) { + res.status(400).send({ error: e.message }); + } +}); + +// ===== TEST ROUTES (Development only) ===== + +if (process.env.NODE_ENV === 'development' || process.env.LOCALE === '1') { + router.post('/test1', async (req, res) => { + const { User } = require('../models/user'); + const sendemail = require('../sendemail'); + + const user = await User.findOne({ + idapp: 1, + username: 'paoloar77' + }); + + if (user) { + await sendemail.sendEmail_Registration( + user.lang, + user.email, + user, + user.idapp, + user.linkreg + ); + } + + res.send({ success: true }); + }); +} + +module.exports = router; \ No newline at end of file diff --git a/src/sendemail.js b/src/sendemail.js index fd17f21..15923a4 100755 --- a/src/sendemail.js +++ b/src/sendemail.js @@ -500,10 +500,12 @@ module.exports = { }, getPathEmail(idapp, email_template) { - const RISO_TEMPLATES = ['reg_notifica_all_invitante']; + const RISO_TEMPLATES = ['reg_notifica_all_invitante', 'reg_email_benvenuto_ammesso']; - if (RISO_TEMPLATES.includes(email_template)) { - return tools.RISO_STR_PATH + '/' + email_template; + if (idapp === '13') { + if (RISO_TEMPLATES.includes(email_template)) { + return tools.RISO_STR_PATH + '/' + email_template; + } } return 'defaultSite/' + email_template; }, @@ -525,6 +527,8 @@ module.exports = { usernameInvitante: user.aportador_solidario, nomeInvitante: nomecognomeInvitante.trim(), nomeInvitato: await User.getNameSurnameEUsernameByUsername(idapp, user.username), + usernameInvitato: user.username, + emailInvitato: user.email, user, }; @@ -534,7 +538,7 @@ module.exports = { if (user.verified_email) { // se l'utente è già stato verificata la sua email, allora gli mando direttamente la email di invito. - quale_email_inviare = 'reg_email_benvenuto_ammesso/' + lang; + quale_email_inviare = this.getPathEmail(idapp, 'reg_email_benvenuto_ammesso') + '/' + lang; } else { // altrimenti gli mando l'email con la richiesta di Verifica email quale_email_inviare = tools.getpathregByIdApp(idapp, lang); @@ -583,7 +587,7 @@ module.exports = { sendEmail_InvitaAmico: async function (lang, emailto, user, idapp, dati) { try { const nomecognomeInvitante = await User.getNameSurnameByUsername(idapp, dati.usernameInvitante, true); - + let mylocalsconf = { idapp, dataemail: await this.getdataemail(idapp), @@ -621,6 +625,7 @@ module.exports = { linkRegistrazione: this.getlinkInvitoReg(idapp, dati), emailto: emailto, usernameInvitante: dati.usernameInvitante, + ammessoUtente: true, }; const ris = await this.sendEmail_base('reg_email_benvenuto_ammesso/' + lang, emailto, mylocalsconf, ''); @@ -705,17 +710,19 @@ module.exports = { await this.sendEmail_base('resetpwd/' + lang, emailto, mylocalsconf, ''); }, - sendEmail_RisRicevuti: async function (lang, userDest, emailto, idapp, myrec) { + sendEmail_RisRicevuti: async function (lang, userDest, emailto, idapp, myrec, extrarec) { console.log('sendEmail_RisRicevuti'); let mylocalsconf = { idapp, + baseurl: tools.getHostByIdApp(idapp), dataemail: await this.getdataemail(idapp), locale: lang, nomeapp: tools.getNomeAppByIdApp(idapp), strlinksito: tools.getHostByIdApp(idapp), emailto: emailto, qty: myrec.qty, + saldoAttuale: extrarec.saldoDest, mittente: decode(myrec.mittente), nomecircuito: decode(myrec.nomecircuito), transactionDate: tools.getstrDate_DD_MM_YYYY(myrec.transactionDate), diff --git a/src/services/AuthService.js b/src/services/AuthService.js index e266775..2867be4 100644 --- a/src/services/AuthService.js +++ b/src/services/AuthService.js @@ -16,6 +16,7 @@ class AuthService { */ async authenticate(idapp, username, password, req) { try { + console.log('STO FACENDO LOGIN...'); // Check if user is blocked if (this.isUserBlocked(username)) { const text = `Utente bloccato. Riprova più tardi. (username=${username})`; @@ -24,13 +25,15 @@ class AuthService { error: true, status: 403, code: server_constants.RIS_CODE_ERR, - message: text + message: text, }; } // Find user by credentials const user = await User.findByCredentials(idapp, username, password); + console.log('user', user); + if (!user) { return await this._handleFailedLogin(idapp, username, req); } @@ -44,27 +47,25 @@ class AuthService { // Prepare user data to send const userToSend = this._prepareUserData(user); + console.log('userToSend', userToSend); + // Check subscription - const subsExistonDb = await this._checkSubscription( - user._id, - req.get('User-Agent') - ); + const subsExistonDb = await this._checkSubscription(user._id, req.get('User-Agent')); return { error: false, token, refreshToken, user: userToSend, - subsExistonDb + subsExistonDb, }; - } catch (error) { console.error('Error in authenticate:', error.message); return { error: true, status: 400, code: server_constants.RIS_CODE_LOGIN_ERR_GENERIC, - message: error.message + message: error.message, }; } } @@ -78,7 +79,7 @@ class AuthService { return { error: true, status: 400, - message: 'Refresh token mancante' + message: 'Refresh token mancante', }; } @@ -88,7 +89,7 @@ class AuthService { return { error: true, status: 403, - message: 'Refresh token non valido' + message: 'Refresh token non valido', }; } @@ -97,15 +98,14 @@ class AuthService { return { error: false, token, - refreshToken: newRefreshToken + refreshToken: newRefreshToken, }; - } catch (error) { console.error('Error in refreshToken:', error.message); return { error: true, status: 500, - message: 'Errore interno del server' + message: 'Errore interno del server', }; } } @@ -128,8 +128,7 @@ class AuthService { */ isUserBlocked(username) { const now = Date.now(); - return this.failedLoginAttempts[username] && - this.failedLoginAttempts[username] > now; + return this.failedLoginAttempts[username] && this.failedLoginAttempts[username] > now; } /** @@ -148,15 +147,17 @@ class AuthService { const loginCheck = await User.tooManyLoginWrong(idapp, username, true); if (loginCheck.troppilogin) { - const text = `Troppe richieste di Login ERRATE: ${username} [IP: ${tools.getiPAddressUser(req)}] Tentativi: ${loginCheck.retry_pwd}`; + const text = `Troppe richieste di Login ERRATE: ${username} [IP: ${tools.getiPAddressUser(req)}] Tentativi: ${ + loginCheck.retry_pwd + }`; await telegrambot.sendMsgTelegramToTheManagers(idapp, text); console.log('/login', text); - + return { error: true, status: 400, code: server_constants.RIS_CODE_ERR, - message: text + message: text, }; } @@ -182,15 +183,17 @@ class AuthService { // Block user after max attempts if (this.failedLoginAttempts[username] >= this.MAX_FAILED_ATTEMPTS) { this.blockUser(username); - const text = `Troppi tentativi di accesso falliti. Utente bloccato (${username}) [IP: ${tools.getiPAddressUser(req)}]`; + const text = `Troppi tentativi di accesso falliti. Utente bloccato (${username}) [IP: ${tools.getiPAddressUser( + req + )}]`; tools.mylogshow(text); await telegrambot.sendMsgTelegramToTheManagers(idapp, text); - + return { error: true, status: 403, code: server_constants.RIS_CODE_ERR, - message: text + message: text, }; } @@ -198,7 +201,7 @@ class AuthService { error: true, status: 401, code: server_constants.RIS_CODE_LOGIN_ERR, - message: 'Credenziali non valide' + message: 'Credenziali non valide', }; } @@ -210,7 +213,7 @@ class AuthService { const shared_consts = require('../tools/shared_nodejs'); const userToSend = new User(); - shared_consts.fieldsUserToChange().forEach(field => { + shared_consts.fieldsUserToChange().forEach((field) => { userToSend[field] = user[field]; }); @@ -226,7 +229,7 @@ class AuthService { const subscription = await Subscription.findOne({ userId, access: 'auth', - browser: userAgent + browser: userAgent, }).lean(); return !!subscription; @@ -237,4 +240,4 @@ class AuthService { } } -module.exports = AuthService; \ No newline at end of file +module.exports = AuthService; diff --git a/src/telegram/telegrambot.js b/src/telegram/telegrambot.js index 9a2a7fd..ed0d079 100644 --- a/src/telegram/telegrambot.js +++ b/src/telegram/telegrambot.js @@ -447,6 +447,7 @@ const txt = { MSG_APORTADOR_USER_REGISTERED: emo.FIRE + ' Si è appena Registrato "%s" (n. %s)\nInvitato da %s', MSG_APORTADOR_ASK_CONFIRM: '🆕💥 🧍‍♂️ %s si sta registrando su %s e ti chiede di poter entrare. Confermi di conoscerla ?', + MSG_APORTADOR_INVITED_REGISTERED: '🆕💥 🧍‍♂️ Complimenti! Il tuo invitato %s si è appena registrato su %s !', MSG_ACCEPT_NEWENTRY_INGROUP: '❇️👥 🧍‍♂️ Accetta Ingresso nel GRUPPO %s:', MSG_FRIENDS_NOT_ACCEPTED_CONFIRMED: '🚫 Hai rifiutato la richiesta di Amicizia di %s !', MSG_HANDSHAKE_NOT_ACCEPTED_CONFIRMED: '🚫 Hai rifiutato la richiesta di Stretta di mano di %s !', @@ -795,7 +796,6 @@ const MyTelegramBot = { text = printf(getstr(langdest, 'MSG_APORTADOR_USER_REGISTERED'), nome, numutenti, aportador); } } else if (phase === this.phase.INVITA_AMICO) { - } let addtext = ''; @@ -903,25 +903,31 @@ const MyTelegramBot = { // Non chiedi la verifica Registrazione await setVerifiedReg(myuser.idapp, myuser.lang, myuser.username, userDest); } else { - msg_notifpush = getstr(langdest, 'MSG_APORTADOR_ASK_CONFIRM', myuser.username, nomeapp); - domanda = getstr(langdest, 'MSG_APORTADOR_ASK_CONFIRM', myuser.username, nomeapp) + '
' + struserinfomsg; - - keyb = cl.getInlineKeyboard(myuser.lang, [ - { - text: '✅ Ammetti ' + myuser.username, - callback_data: InlineConferma.RISPOSTA_SI + myfunc + tools.SEP + myuser.username + tools.SEP + userDest, - }, - /*{ + if (myuser.verified_by_aportador) { + msg_notifpush = getstr(langdest, 'MSG_APORTADOR_INVITED_REGISTERED', myuser.username, nomeapp); + domanda = + getstr(langdest, 'MSG_APORTADOR_INVITED_REGISTERED', myuser.username, nomeapp) + '
' + struserinfomsg; + } else { + msg_notifpush = getstr(langdest, 'MSG_APORTADOR_ASK_CONFIRM', myuser.username, nomeapp); + domanda = getstr(langdest, 'MSG_APORTADOR_ASK_CONFIRM', myuser.username, nomeapp) + '
' + struserinfomsg; + keyb = cl.getInlineKeyboard(myuser.lang, [ + { + text: '✅ Ammetti ' + myuser.username, + callback_data: InlineConferma.RISPOSTA_SI + myfunc + tools.SEP + myuser.username + tools.SEP + userDest, + }, + ]); + } + /*{ text: '🚫 Rifiuta ' + myuser.username, callback_data: InlineConferma.RISPOSTA_NO + myfunc + tools.SEP + myuser.username + tools.SEP + userDest, }, */ - ]); } send_notif = true; } else if (myfunc === shared_consts.CallFunz.VERIFICA_TELEGRAM) { if (telegid > 0) { cl.setPhotoProfile(myuser, telegid, false); + const rismsg = await MsgTemplate.getMsgByLang( idapp, myuser, @@ -930,6 +936,23 @@ const MyTelegramBot = { ); await cl.sendMsgLog(telegid, rismsg.body); + + // Invia notifica Teelgram all'Invitante che il suo invitato si è Verificato con Telegram. + userDest = myuser.aportador_solidario; + let useraportador = await User.getUserShortDataByUsername(idapp, userDest); + + + const rismsg2 = await MsgTemplate.getMsgByLang( + idapp, + myuser, + shared_consts.TypeMsgTemplate.MSG_VERIFICA_TELEGRAM_COMPLETATA_NOTIF_INVITANTE, + myuser.lang + ); + + + const telegidInvitante = useraportador.profile.teleg_id; + + await cl.sendMsgLog(telegidInvitante, rismsg2.body); } } else if (myfunc === shared_consts.CallFunz.RICHIESTA_GRUPPO) { msg_notifpush = printf(getstr(langdest, 'MSG_ACCEPT_NEWENTRY_INGROUP'), name); @@ -1091,6 +1114,7 @@ const MyTelegramBot = { } }, + askConfirmationUserFriend: async function (idapp, myfunc, myuser, userDest = '', username = '') { try { const cl = getclTelegByidapp(idapp); @@ -1255,22 +1279,7 @@ const MyTelegramBot = { let title = ''; let msg = ''; - if (mydata.tipomsg === tools.TipoMsg.SEND_LINK_CHAT_DONATORI) { - if (sonosognatore) - msg = printf( - tools.gettranslate('SEND_LINK_CHAT_SOGNATORE', lang), - user.name, - mydata.navemediatore.riga + '.' + mydata.navemediatore.col, - mydata.msgpar1 - ); - else - msg = printf( - tools.gettranslate('SEND_LINK_CHAT_DONATORI', lang), - user.name, - mydata.navemediatore.riga + '.' + mydata.navemediatore.col, - mydata.msgpar1 - ); - } else if (mydata.tipomsg === tools.TipoMsg.SEND_MSG || mydata.tipomsg === tools.TipoMsg.SEND_MSG_SINGOLO) { + if (mydata.tipomsg === tools.TipoMsg.SEND_MSG || mydata.tipomsg === tools.TipoMsg.SEND_MSG_SINGOLO) { if (!!mydata.username_mitt) { msg = '[' + tools.gettranslate('MSG_SEND_FROM', lang) + ' ' + mydata.username_mitt + ']:' + tools.ACAPO; } @@ -1285,32 +1294,6 @@ const MyTelegramBot = { if (cl) { msg = await tools.convertSpecialTags(rec.user, msg); } - - if (!!mydata.flotta) { - // SOSTITUISCI LE PAROLE CHIAVI - if (!!mydata.flotta.date_start) - msg = msg.replace('{date_start}', tools.getstrDateLongTot(new Date(mydata.flotta.date_start), user.lang)); - if (!!mydata.flotta.date_close) - msg = msg.replace('{date_close}', tools.getstrDateLongTot(new Date(mydata.flotta.date_close), user.lang)); - if (!!mydata.flotta.link_superchat) msg = msg.replace('{link_superchat}', mydata.flotta.link_superchat); - if (!!mydata.flotta.tutor1) msg = msg.replace('{tutor1}', mydata.flotta.tutor1); - if (!!mydata.flotta.tutor2) msg = msg.replace('{tutor2}', mydata.flotta.tutor2); - if (!!mydata.flotta.tutor3) msg = msg.replace('{tutor3}', mydata.flotta.tutor3); - if (!!mydata.flotta.tutorslo) msg = msg.replace('{tutorslo}', mydata.flotta.tutorslo); - if (!!mydata.flotta.sognatore_nomecognome) msg = msg.replace('{sognatore}', mydata.flotta.sognatore_nomecognome); - if (!!mydata.flotta.sognatore_nomecognome) - msg = msg.replace( - '{flotta}', - mydata.flotta.riga + - '.' + - Math.ceil(mydata.flotta.col_prima / 8) + - ' - ' + - mydata.flotta.riga + - '.' + - Math.ceil(mydata.flotta.col_ultima / 8) - ); - } - return { body: msg, title }; }, @@ -1926,7 +1909,7 @@ class Telegram { risp = 'Siiiii ! Davvero! ' + emo.DREAM; } else if (MsgBot.PAROLACCE.find((rec) => testo.indexOf(rec) > -1)) { risp = "Da te non me l'aspettavo proprio !! " + emo.INNOCENT + emo.CROSS_ROSSA; - // } else if (MsgBot.OK.find((rec) => testo.indexOf(rec) > -1)) { + // } else if (MsgBot.OK.find((rec) => testo.indexOf(rec) > -1)) { // risp = '👍🏻'; } else if (MsgBot.CUORE.find((rec) => testo.indexOf(rec) > -1)) { risp = '❤️💚💜'; @@ -3332,27 +3315,27 @@ class Telegram { if (!msg.from.username) { rec.cmdAfterVerified === shared_consts.CallFunz.VERIFICA_TELEGRAM; } else { - await this.verificaTelegramCompleted(msg); + await this.verificaTelegramCompleted(msg, recuser); } } + } } - async verificaTelegramCompleted(msg) { + async verificaTelegramCompleted(msg, recuser) { try { const rec = this.getRecInMem(msg); - const id = msg.chat.id; - const recuser = this.getRecInMemById(id); - if (recuser) { + if (rec && recuser) { await User.setUsernameTelegram( this.idapp, - recuser.user._id, + recuser._id, msg.from.username || '', msg.from.first_name || '', msg.from.last_name || '' ); + rec.status = Status.VERIFIED; rec.datemenu_updated = null; rec.menuDb = null; @@ -4595,7 +4578,6 @@ if (true) { ); // Invia una email alla persona che è stata ammessa - await local_sendMsgTelegram(user.idapp, data.username, msgOrig); await local_sendMsgTelegram(user.idapp, data.userDest, msgDest); diff --git a/src/tools/general.js b/src/tools/general.js index c4972d2..a3c19aa 100755 --- a/src/tools/general.js +++ b/src/tools/general.js @@ -2145,7 +2145,6 @@ module.exports = { } }, - getTelegramKeyByIdApp: function (idapp) { if (this.MYAPPS.length === 0) { console.error('❌ this.MYAPPS VUOTI!!', this.MYAPPS); @@ -3942,7 +3941,7 @@ module.exports = { try { return await this.readfilecontent(__dirname + '/../version.txt'); } catch (e) { - return '' + return ''; } }, @@ -4450,12 +4449,34 @@ module.exports = { }, getNomeCognomeEUserNameByUser(user) { - let nome = `${user.name} ${user.surname} (${user.username})`; - if (!user.name) { - nome = user.username; + if (!user) return ''; + + const name = user.name?.trim() || ''; + const surname = user.surname?.trim() || ''; + const username = user.username?.trim() || ''; + + // Se ci sono nome e cognome + if (name && surname) { + return username ? `${name} ${surname} (${username})` : `${name} ${surname}`; } - return nome; + // Se c'è solo il nome + if (name) { + return username ? `${name} (${username})` : name; + } + + // Se c'è solo il cognome + if (surname) { + return username ? `${surname} (${username})` : surname; + } + + // Se c'è solo username + if (username) { + return username; + } + + // Nessun dato disponibile + return ''; }, sulServer() { @@ -4527,31 +4548,45 @@ module.exports = { try { if (!msg) return msg; - if (!!user) { + if (user) { + // Usa replaceAll() per sostituire TUTTE le occorrenze (non solo la prima) if (msg.includes('{host}')) { - msg = msg.replace('{host}', this.getHostByIdApp(user.idapp)); + msg = msg.replaceAll('{host}', this.getHostByIdApp(user.idapp)); + } + if (msg.includes('{appname}')) { + msg = msg.replaceAll('{appname}', this.getNomeAppByIdApp(user.idapp)); } - if (msg.includes('{appname}')) msg = msg.replace('{appname}', this.getNomeAppByIdApp(user.idapp)); - msg = msg.replace('{username}', user.username); - // msg = await this.checkStr(msg, '{time_exp_reg}', user, 1); - msg = msg.replace('{name}', user.name ? user.name : user.username); - msg = msg.replace('{surname}', user.surname ? user.surname : ''); - msg = msg.replace('{urlunsubscribe_user}', this.getUnsubsribeUrl_User(user)); + msg = msg.replaceAll('{username}', user.username || ''); + msg = msg.replaceAll('{name}', user.name || user.username || ''); + msg = msg.replaceAll('{surname}', user.surname || ''); + msg = msg.replaceAll('{urlunsubscribe_user}', this.getUnsubsribeUrl_User(user)); + msg = msg.replaceAll('{aportador_solidario}', user.aportador_solidario || ''); - msg = msg.replace('{aportador_solidario}', user.aportador_solidario ? user.aportador_solidario : ''); - if (!!user.profile.link_payment) msg = msg.replace('{link_paypalme}', user.profile.link_payment); - if (!!user.profile.revolut) msg = msg.replace('{revolut}', user.profile.revolut); - if (!!user.profile.payeer_id) msg = msg.replace('{payeer_id}', user.profile.payeer_id); - if (!!user.profile.advcash_id) msg = msg.replace('{advcash_id}', user.profile.advcash_id); - if (!!user.profile.email_paypal) msg = msg.replace('{email_paypal}', user.profile.email_paypal); - if (!!user.profile.note_payment) msg = msg.replace('{note_payment}', user.profile.note_payment); + // Usa optional chaining per evitare errori se user.profile è undefined + if (user.profile?.link_payment) { + msg = msg.replaceAll('{link_paypalme}', user.profile.link_payment); + } + if (user.profile?.revolut) { + msg = msg.replaceAll('{revolut}', user.profile.revolut); + } + if (user.profile?.payeer_id) { + msg = msg.replaceAll('{payeer_id}', user.profile.payeer_id); + } + if (user.profile?.advcash_id) { + msg = msg.replaceAll('{advcash_id}', user.profile.advcash_id); + } + if (user.profile?.email_paypal) { + msg = msg.replaceAll('{email_paypal}', user.profile.email_paypal); + } + if (user.profile?.note_payment) { + msg = msg.replaceAll('{note_payment}', user.profile.note_payment); + } } - // const cl = getclTelegByidapp(user.idapp); - msg = msg.replace('{link_chathelp}', this.HELP_CHAT); + msg = msg.replaceAll('{link_chathelp}', this.HELP_CHAT); } catch (e) { - console.log(e); + console.error('Errore in convertSpecialTags:', e); } return msg; @@ -4965,7 +5000,7 @@ module.exports = { mystr = i18n.__( 'DATE_1DAY', this.getstrDateLong(myevent.dateTimeStart), - this.getstrTime(myevent.dateTimeStart), + this.getstrTime(myevent.dateTimeStart) ); } else { mystr = i18n.__( @@ -6305,7 +6340,6 @@ module.exports = { getTokenRandom() { return crypto.randomBytes(32).toString('hex'); - }, async ensureDir(fullnamepath) { diff --git a/src/tools/shared_nodejs.js b/src/tools/shared_nodejs.js index de83c6c..4fe9e0d 100755 --- a/src/tools/shared_nodejs.js +++ b/src/tools/shared_nodejs.js @@ -597,6 +597,7 @@ module.exports = { MSG_BENV_REGISTRATO: 2020, MSG_INVITE_WHATSAPP: 2040, MSG_VERIFICA_TELEGRAM_COMPLETATA: 2050, + MSG_VERIFICA_TELEGRAM_COMPLETATA_NOTIF_INVITANTE: 2060, }, TypeSend: {