diff --git a/emails/RISO/reg_chiedi_ammettere_all_invitante/it/html.pug b/emails/RISO/reg_chiedi_ammettere_all_invitante/it/html.pug new file mode 100755 index 0000000..15116fe --- /dev/null +++ b/emails/RISO/reg_chiedi_ammettere_all_invitante/it/html.pug @@ -0,0 +1,371 @@ +doctype html +html(lang="it") + head + meta(charset="UTF-8") + meta(name="viewport" content="width=device-width, initial-scale=1.0") + style(type="text/css"). + * { + margin: 0; + padding: 0; + box-sizing: border-box; + } + + body { + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; + background-color: #f5f5f5; + padding: 20px; + line-height: 1.6; + } + + .header-logo { + width: 120px; + height: auto; + margin-bottom: 16px; + display: block; + margin-left: auto; + margin-right: auto; + } + + .email-container { + max-width: 600px; + margin: 0 auto; + background: white; + border-radius: 12px; + box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1); + overflow: hidden; + } + + .email-header { + background: linear-gradient(135deg, #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; + } + + .alert-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; + } + + .request-card { + background: linear-gradient(135deg, #fff8dc 0%, #fef9f3 100%); + border: 2px solid #f0ad4e; + border-radius: 8px; + padding: 24px; + margin: 20px 0; + text-align: center; + } + + .request-card h3 { + font-size: 14px; + text-transform: uppercase; + color: #f0ad4e; + margin-bottom: 12px; + letter-spacing: 0.5px; + font-weight: 600; + } + + .request-card .member-name { + font-size: 28px; + color: #1a1a1a; + font-weight: 700; + margin-bottom: 8px; + } + + .request-card .member-detail { + font-size: 15px; + color: #555; + margin: 6px 0; + } + + .request-card .member-detail strong { + color: #f0ad4e; + } + + .question-box { + background: #fff3cd; + border-left: 4px solid #f0ad4e; + border-radius: 8px; + padding: 20px; + margin: 24px 0; + text-align: center; + } + + .question-box p { + font-size: 20px; + color: #1a1a1a; + font-weight: 600; + margin: 0; + line-height: 1.4; + } + + .cta-section { + text-align: center; + margin: 32px 0; + padding: 24px 0; + border-top: 2px solid #e0e0e0; + border-bottom: 2px solid #e0e0e0; + } + + .cta-title { + font-size: 18px; + font-weight: 600; + color: #1a1a1a; + margin-bottom: 20px; + } + + .cta-button { + display: inline-block; + padding: 18px 56px; + font-size: 20px; + font-weight: 700; + color: white; + background: linear-gradient(135deg, #7cb342 0%, #558b2f 100%); + border-radius: 50px; + text-decoration: none; + box-shadow: 0 6px 20px rgba(124, 179, 66, 0.4); + transition: all 0.3s ease; + } + + .button-icon { + font-size: 20px; + margin-right: 10px; + vertical-align: middle; + } + + .info-box { + background: #e8f5e9; + border-radius: 8px; + padding: 16px; + margin: 20px 0; + } + + .info-box p { + margin: 0 0 8px 0; + color: #2e7d32; + font-size: 15px; + line-height: 1.6; + } + + .info-box p:last-child { + margin-bottom: 0; + } + + .warning-box { + background: #f8d7da; + border-left: 4px solid #dc3545; + border-radius: 8px; + padding: 16px; + margin: 20px 0; + } + + .warning-box p { + margin: 0; + color: #721c24; + font-size: 15px; + line-height: 1.6; + } + + .warning-box strong { + color: #dc3545; + } + + .responsibility-box { + background: #f8f9fa; + border-radius: 8px; + padding: 20px; + margin: 20px 0; + } + + .responsibility-box h3 { + font-size: 17px; + color: #1a1a1a; + margin-bottom: 12px; + text-align: center; + font-weight: 600; + } + + .responsibility-item { + display: flex; + align-items: flex-start; + margin-bottom: 10px; + padding: 6px 0; + } + + .responsibility-icon { + font-size: 20px; + margin-right: 10px; + min-width: 24px; + flex-shrink: 0; + } + + .responsibility-text { + font-size: 15px; + color: #555; + line-height: 1.5; + } + + .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; + } + + .alert-icon { + font-size: 48px; + } + + .email-body { + padding: 20px 16px; + } + + .request-card .member-name { + font-size: 24px; + } + + .question-box p { + font-size: 18px; + } + + .cta-button { + padding: 16px 40px; + font-size: 18px; + width: 100%; + max-width: 300px; + } + + .responsibility-item { + font-size: 14px; + } + } + + body + .email-container + //- Header + .email-header + img.header-logo(src=baseurl+'/images/logo.png' alt='RISO - Rete Italiana Scambio Orizzontale') + h1 🔔 Richiesta di Ammissione + p.subtitle Nuovo membro in attesa + + //- Body + .email-body + //- Intro + .intro-text + | Ciao #{nomeInvitante},
+ | hai una nuova richiesta di ammissione da confermare! + + //- Card richiesta + .request-card + h3 👤 Richiesta di Ingresso + .member-name #{usernameInvitato} + if nomeInvitato + .member-detail + strong Nome: + | #{nomeInvitato} + if emailInvitato + .member-detail + strong Email: + | #{emailInvitato} + + //- Domanda di conferma + .question-box + p 🤔 Confermi di conoscere #{nomeInvitato}? + + //- CTA principale + .cta-section + .cta-title Ammetti #{usernameInvitato} alla comunità RISO + a.cta-button(href=linkAmmissione target="_blank") + span.button-icon ✓ + | Sì, Confermo + + //- Responsabilità + .responsibility-box + h3 📋 La tua responsabilità come invitante + .responsibility-item + span.responsibility-icon 🤝 + span.responsibility-text + strong Conoscenza diretta: + | Dovresti ammettere solo persone che conosci personalmente e di cui ti fidi + .responsibility-item + span.responsibility-icon 🛡️ + span.responsibility-text + strong Fiducia: + | L'ammissione si basa sulla fiducia reciproca nella comunità RISO + .responsibility-item + span.responsibility-icon 👥 + span.responsibility-text + strong Supporto: + | Come invitante, aiuterai il nuovo membro a integrarsi nella comunità + + //- Info box + .info-box + p + | ✓ Dopo l'ammissione, #{usernameInvitato} potrà completare il profilo + p + | ✓ Il facilitatore locale valuterà l'abilitazione all'uso dei RIS + + //- Warning box + .warning-box + p + strong ⚠️ Importante: + | Se non conosci questa persona o hai dubbi sull'ammissione, ti consigliamo di non procedere. Puoi contattare il facilitatore locale per ulteriori informazioni o semplicemente non cliccare sul pulsante di conferma. + + //- Footer + .email-footer + .divider + p Hai ricevuto questa email perché #{usernameInvitato} ha indicato te come invitante 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/emails/RISO/reg_chiedi_ammettere_all_invitante/it/subject.pug b/emails/RISO/reg_chiedi_ammettere_all_invitante/it/subject.pug new file mode 100755 index 0000000..974f2b2 --- /dev/null +++ b/emails/RISO/reg_chiedi_ammettere_all_invitante/it/subject.pug @@ -0,0 +1 @@ +=`🎉 ${name ? ', ' + name : username} chiede di essere ammesso su ${nomeapp} !` diff --git a/emails/defaultSite/reg_chiedi_ammettere_all_invitante/it/html.pug b/emails/defaultSite/reg_chiedi_ammettere_all_invitante/it/html.pug new file mode 100755 index 0000000..46ed5d1 --- /dev/null +++ b/emails/defaultSite/reg_chiedi_ammettere_all_invitante/it/html.pug @@ -0,0 +1,371 @@ +doctype html +html(lang="it") + head + meta(charset="UTF-8") + meta(name="viewport" content="width=device-width, initial-scale=1.0") + style(type="text/css"). + * { + margin: 0; + padding: 0; + box-sizing: border-box; + } + + body { + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; + background-color: #f5f5f5; + padding: 20px; + line-height: 1.6; + } + + .header-logo { + width: 120px; + height: auto; + margin-bottom: 16px; + display: block; + margin-left: auto; + margin-right: auto; + } + + .email-container { + max-width: 600px; + margin: 0 auto; + background: white; + border-radius: 12px; + box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1); + overflow: hidden; + } + + .email-header { + background: linear-gradient(135deg, #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; + } + + .alert-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; + } + + .request-card { + background: linear-gradient(135deg, #fff8dc 0%, #fef9f3 100%); + border: 2px solid #f0ad4e; + border-radius: 8px; + padding: 24px; + margin: 20px 0; + text-align: center; + } + + .request-card h3 { + font-size: 14px; + text-transform: uppercase; + color: #f0ad4e; + margin-bottom: 12px; + letter-spacing: 0.5px; + font-weight: 600; + } + + .request-card .member-name { + font-size: 28px; + color: #1a1a1a; + font-weight: 700; + margin-bottom: 8px; + } + + .request-card .member-detail { + font-size: 15px; + color: #555; + margin: 6px 0; + } + + .request-card .member-detail strong { + color: #f0ad4e; + } + + .question-box { + background: #fff3cd; + border-left: 4px solid #f0ad4e; + border-radius: 8px; + padding: 20px; + margin: 24px 0; + text-align: center; + } + + .question-box p { + font-size: 20px; + color: #1a1a1a; + font-weight: 600; + margin: 0; + line-height: 1.4; + } + + .cta-section { + text-align: center; + margin: 32px 0; + padding: 24px 0; + border-top: 2px solid #e0e0e0; + border-bottom: 2px solid #e0e0e0; + } + + .cta-title { + font-size: 18px; + font-weight: 600; + color: #1a1a1a; + margin-bottom: 20px; + } + + .cta-button { + display: inline-block; + padding: 18px 56px; + font-size: 20px; + font-weight: 700; + color: white; + background: linear-gradient(135deg, #7cb342 0%, #558b2f 100%); + border-radius: 50px; + text-decoration: none; + box-shadow: 0 6px 20px rgba(124, 179, 66, 0.4); + transition: all 0.3s ease; + } + + .button-icon { + font-size: 20px; + margin-right: 10px; + vertical-align: middle; + } + + .info-box { + background: #e8f5e9; + border-radius: 8px; + padding: 16px; + margin: 20px 0; + } + + .info-box p { + margin: 0 0 8px 0; + color: #2e7d32; + font-size: 15px; + line-height: 1.6; + } + + .info-box p:last-child { + margin-bottom: 0; + } + + .warning-box { + background: #f8d7da; + border-left: 4px solid #dc3545; + border-radius: 8px; + padding: 16px; + margin: 20px 0; + } + + .warning-box p { + margin: 0; + color: #721c24; + font-size: 15px; + line-height: 1.6; + } + + .warning-box strong { + color: #dc3545; + } + + .responsibility-box { + background: #f8f9fa; + border-radius: 8px; + padding: 20px; + margin: 20px 0; + } + + .responsibility-box h3 { + font-size: 17px; + color: #1a1a1a; + margin-bottom: 12px; + text-align: center; + font-weight: 600; + } + + .responsibility-item { + display: flex; + align-items: flex-start; + margin-bottom: 10px; + padding: 6px 0; + } + + .responsibility-icon { + font-size: 20px; + margin-right: 10px; + min-width: 24px; + flex-shrink: 0; + } + + .responsibility-text { + font-size: 15px; + color: #555; + line-height: 1.5; + } + + .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; + } + + .alert-icon { + font-size: 48px; + } + + .email-body { + padding: 20px 16px; + } + + .request-card .member-name { + font-size: 24px; + } + + .question-box p { + font-size: 18px; + } + + .cta-button { + padding: 16px 40px; + font-size: 18px; + width: 100%; + max-width: 300px; + } + + .responsibility-item { + font-size: 14px; + } + } + + body + .email-container + //- Header + .email-header + img.header-logo(src=baseurl+'/images/logo.png' alt=nomeapp) + h1 🔔 Richiesta di Ammissione + p.subtitle Nuovo membro in attesa + + //- Body + .email-body + //- Intro + .intro-text + | Ciao #{nomeInvitante},
+ | hai una nuova richiesta di ammissione da confermare! + + //- Card richiesta + .request-card + h3 👤 Richiesta di Ingresso + .member-name #{usernameInvitato} + if nomeInvitato + .member-detail + strong Nome: + | #{nomeInvitato} + if emailInvitato + .member-detail + strong Email: + | #{emailInvitato} + + //- Domanda di conferma + .question-box + p 🤔 Confermi di conoscere #{nomeInvitato}? + + //- CTA principale + .cta-section + .cta-title Ammetti #{usernameInvitato} su #{nomeapp} + a.cta-button(href=linkAmmissione target="_blank") + span.button-icon ✓ + | Sì, Confermo + + //- Responsabilità + .responsibility-box + h3 📋 La tua responsabilità come invitante + .responsibility-item + span.responsibility-icon 🤝 + span.responsibility-text + strong Conoscenza diretta: + | Dovresti ammettere solo persone che conosci personalmente e di cui ti fidi + .responsibility-item + span.responsibility-icon 🛡️ + span.responsibility-text + strong Fiducia: + | L'ammissione si basa sulla fiducia reciproca nella piattaforma su #{nomeapp} + .responsibility-item + span.responsibility-icon 👥 + span.responsibility-text + strong Supporto: + | Come invitante, aiuterai il nuovo membro a integrarsi nella comunità + + //- Info box + .info-box + p + | ✓ Dopo l'ammissione, #{usernameInvitato} potrà completare il profilo + p + | ✓ Il facilitatore locale valuterà l'abilitazione all'uso dei RIS + + //- Warning box + .warning-box + p + strong ⚠️ Importante: + | Se non conosci questa persona o hai dubbi sull'ammissione, ti consigliamo di non procedere. Puoi contattare il facilitatore locale per ulteriori informazioni o semplicemente non cliccare sul pulsante di conferma. + + //- Footer + .email-footer + .divider + p Hai ricevuto questa email perché #{usernameInvitato} ha indicato te come invitante 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/emails/defaultSite/reg_chiedi_ammettere_all_invitante/it/subject.pug b/emails/defaultSite/reg_chiedi_ammettere_all_invitante/it/subject.pug new file mode 100755 index 0000000..974f2b2 --- /dev/null +++ b/emails/defaultSite/reg_chiedi_ammettere_all_invitante/it/subject.pug @@ -0,0 +1 @@ +=`🎉 ${name ? ', ' + name : username} chiede di essere ammesso su ${nomeapp} !` diff --git a/emails/invitaamico/it/html.pug b/emails/invitaamico/it/html.pug index e05d573..3ffd215 100644 --- a/emails/invitaamico/it/html.pug +++ b/emails/invitaamico/it/html.pug @@ -331,7 +331,7 @@ html(lang="it") .riso-info h3 🍚 Cos'è il Progetto RISO? p - | RISO è una rete di comunità territoriali in tutta Italia dove puoi scambiare beni, servizi e ospitalità con altre persone, usando il baratto, il dono, oppure la moneta complementare RIS. + | RISO è una rete di comunità territoriali in tutta Italia dove puoi scambiare beni, servizi e ospitalità con altre persone, usando il baratto, il dono, oppure in RIS. p | Non è un marketplace commerciale: è una comunità basata su fiducia e relazioni reali tra persone che si conoscono e si incontrano. @@ -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é, ma solo come unità di misura degli scambi + | Non speculativo: il RIS non è una moneta complementare, è un Sistema di Credito Naturale. Non serve a 'comprare' cose, ma a misurare e scambiare l'energia umana. .value-item span.benefit-icon 🌍 | Sostenibilità: Promuoviamo stili di vita sani e naturali diff --git a/emails/registration/it/html.pug b/emails/registration/it/html.pug index 7a6fc9e..d2b948c 100755 --- a/emails/registration/it/html.pug +++ b/emails/registration/it/html.pug @@ -16,14 +16,15 @@ html(lang="it") padding: 20px; line-height: 1.6; } + .header-logo { - width: 80px; + width: 120px; height: auto; margin-bottom: 16px; display: block; margin-left: auto; margin-right: auto; - } + } .email-container { max-width: 600px; @@ -35,7 +36,7 @@ html(lang="it") } .email-header { - background: linear-gradient(135deg, #027be3 0%, #0056b3 100%); + background: linear-gradient(135deg, #7cb342 0%, #558b2f 100%); color: white; padding: 40px 24px; text-align: center; @@ -43,90 +44,39 @@ html(lang="it") .email-header h1 { margin: 0 0 8px 0; - font-size: 28px; + font-size: 26px; font-weight: 600; + line-height: 1.3; } - .email-header p { - margin: 0; - font-size: 16px; + .email-header .subtitle { + margin: 8px 0 0 0; + font-size: 17px; opacity: 0.95; + font-style: italic; } .welcome-icon { - font-size: 48px; - margin-bottom: 16px; + font-size: 56px; + margin-bottom: 12px; } .email-body { - padding: 20px 16px; + padding: 32px 24px; } .intro-text { font-size: 16px; color: #333; - margin-bottom: 16px; + margin-bottom: 20px; text-align: center; line-height: 1.7; } - .credentials-box { - background: #f8f9fa; - border-left: 4px solid #027be3; - border-radius: 8px; - padding: 12px; - margin-bottom: 16px; - } - - .credentials-title { - font-size: 15px; - font-weight: 600; - color: #555; - margin-bottom: 8px; - text-transform: uppercase; - letter-spacing: 0.5px; - } - - .credential-row { - display: flex; - align-items: center; - padding: 6px 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: #027be3; - text-decoration: none; - } - - .credential-value a:hover { - text-decoration: underline; - } - .cta-section { text-align: center; - margin: 16px 0; - padding: 16px 0; + margin: 24px 0; + padding: 20px 0; border-top: 1px solid #e0e0e0; border-bottom: 1px solid #e0e0e0; } @@ -138,57 +88,22 @@ html(lang="it") margin-bottom: 16px; } - .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 32px; - font-size: 16px; + padding: 16px 48px; + font-size: 18px; font-weight: 600; color: white; - background: linear-gradient(135deg, #027be3 0%, #0056b3 100%); + background: linear-gradient(135deg, #7cb342 0%, #558b2f 100%); border-radius: 50px; text-decoration: none; - box-shadow: 0 4px 12px rgba(2, 123, 227, 0.3); - transition: transform 0.2s, box-shadow 0.2s; - flex: 1; - min-width: 180px; - max-width: 220px; - } - - .cta-button:hover { - transform: translateY(-2px); - box-shadow: 0 6px 16px rgba(2, 123, 227, 0.4); - } - - .cta-button-secondary { - background: linear-gradient(135deg, #28a745 0%, #1e7e34 100%); - box-shadow: 0 4px 12px rgba(40, 167, 69, 0.3); - } - - .cta-button-secondary:hover { - box-shadow: 0 6px 16px rgba(40, 167, 69, 0.4); - } - - .cta-button-tertiary { - background: linear-gradient(135deg, #ff9800 0%, #f57c00 100%); - box-shadow: 0 4px 12px rgba(255, 152, 0, 0.3); - } - - .cta-button-tertiary:hover { - box-shadow: 0 6px 16px rgba(255, 152, 0, 0.4); + box-shadow: 0 4px 12px rgba(124, 179, 66, 0.3); + transition: all 0.3s ease; } .button-icon { font-size: 18px; - margin-right: 6px; + margin-right: 8px; vertical-align: middle; } @@ -196,31 +111,114 @@ html(lang="it") margin-top: 16px; font-size: 13px; color: #777; + line-height: 1.6; } .alternative-link a { - color: #027be3; + color: #558b2f; text-decoration: none; word-break: break-all; } - .info-box { - background: #e3f2fd; + .verification-process { + background: #f8f9fa; border-radius: 8px; - padding: 10px; - margin-top: 12px; - text-align: center; + padding: 24px 20px; + margin: 24px 0; } - .info-box p { + .process-title { + font-size: 18px; + font-weight: 600; + color: #1a1a1a; + text-align: center; + margin-bottom: 20px; + } + + .process-title .icon { + font-size: 24px; + margin-right: 8px; + vertical-align: middle; + } + + .process-steps { + margin: 20px 0; + } + + .process-step { + display: flex; + align-items: flex-start; + margin-bottom: 20px; + padding: 16px; + background: white; + border-radius: 8px; + border-left: 4px solid #e0e0e0; + } + + .process-step.active { + border-left-color: #7cb342; + background: linear-gradient(135deg, #f8fdf8 0%, #e8f5e9 100%); + } + + .step-badge { + min-width: 40px; + height: 40px; + border-radius: 50%; + background: #e0e0e0; + color: #666; + display: flex; + align-items: center; + justify-content: center; + font-weight: 700; + font-size: 18px; + margin-right: 16px; + flex-shrink: 0; + } + + .process-step.active .step-badge { + background: linear-gradient(135deg, #7cb342 0%, #558b2f 100%); + color: white; + } + + .step-content { + flex: 1; + } + + .step-content h4 { + font-size: 16px; + color: #1a1a1a; + margin-bottom: 6px; + font-weight: 600; + } + + .step-content p { + font-size: 15px; + color: #555; + line-height: 1.5; margin: 0; - color: #1565c0; - font-size: 14px; + } + + .info-note { + background: #fff8dc; + border-left: 4px solid #7cb342; + border-radius: 8px; + padding: 14px; + margin-top: 20px; + } + + .info-note p { + margin: 0; + font-size: 15px; + color: #1a1a1a; line-height: 1.6; } + .info-note strong { + color: #558b2f; + } + .email-footer { - padding: 16px 12px; + padding: 20px; text-align: center; background: #f8f9fa; color: #777; @@ -234,115 +232,132 @@ html(lang="it") .divider { height: 1px; background: linear-gradient(to right, transparent, #e0e0e0, transparent); - margin: 24px 0; + margin: 20px 0; } @media only screen and (max-width: 600px) { body { - padding: 5px; + padding: 10px; } .email-header { - padding: 16px 10px; + padding: 24px 16px; } .email-header h1 { - font-size: 24px; + font-size: 22px; + } + + .welcome-icon { + font-size: 48px; } .email-body { - padding: 16px 10px; - } - - .credentials-box { padding: 20px 16px; } - .credential-row { - flex-direction: column; - align-items: flex-start; - } - - .credential-label { - margin-bottom: 4px; - font-size: 13px; - } - - .credential-value { - font-size: 14px; - } - - .cta-buttons-wrapper { - flex-direction: column; - gap: 12px; - } - .cta-button { - padding: 14px 24px; - font-size: 15px; + padding: 14px 32px; + font-size: 16px; width: 100%; - max-width: 100%; + max-width: 300px; + } + + .verification-process { + padding: 20px 16px; + } + + .process-step { + padding: 12px; + } + + .step-badge { + min-width: 36px; + height: 36px; + font-size: 16px; + margin-right: 12px; + } + + .step-content h4 { + font-size: 15px; + } + + .step-content p { + font-size: 14px; } } body .email-container + //- Header .email-header - - var baseimg = baseurl + '/'; - img.header-logo(src=baseimg+"images/logo.png" alt=nomeapp || 'Logo') - h1 Benvenuto #{name ? ', ' + name : username} - | su #{nomeapp || 'la nostra piattaforma'}! + - var baseimg = baseurl + '/'; + img.header-logo(src=baseimg+"images/logo.png" alt=nomeapp || 'RISO') + h1 Benvenuto/a #{name ? name : username} su #{nomeapp}! + p.subtitle Rete Italiana Scambio Orizzontale + //- Body .email-body if !verified_email .intro-text - | Verifica il tuo indirizzo email cliccando sul pulsante qui sotto. + | Per iniziare il tuo percorso in RISO, verifica il tuo indirizzo email cliccando sul pulsante qui sotto. + .cta-section - .cta-title 🔐 1. Verifica il tuo account + .cta-title 🔐 Verifica il tuo account if strlinkreg a.cta-button(href=strlinkreg target="_blank") span.button-icon ✓ - | Verifica Registrazione + | Verifica Email .alternative-link | Oppure copia e incolla questo link nel tuo browser: br a(href=strlinkreg target="_blank") #{strlinkreg} - + + //- Processo di verifica .verification-process .process-title - span.icon 📋 + span.icon 🌱 | Il tuo percorso di ingresso in RISO .process-steps .process-step .step-badge 1 .step-content - h4 ✓ Verifica la tua email: - p Cliccando sul bottone qui sopra. + h4 ✓ Verifica la tua email + p Clicca sul pulsante sopra per confermare il tuo indirizzo email. .process-step.active .step-badge 2 .step-content h4 ⏳ In attesa di ammissione - p Il tuo invitante vedrà la tua richiesta. Riceverai un'email appena sarai ammesso ! + p Il tuo invitante vedrà la tua richiesta. Riceverai un'email appena sarai ammesso! .process-step .step-badge 3 .step-content - h4 🎉 Accesso alla piattaforma - p Potrai così accedere e completare il tuo profilo per iniziare a fare parte della comunità RISO. + h4 🎯 Completa il tuo profilo + p Una volta ammesso, potrai completare il tuo profilo e iniziare a fare parte della comunità RISO. + + .process-step + .step-badge 4 + .step-content + h4 🍚 Inizia a scambiare + p Crea annunci, scambia beni e servizi, e partecipa agli eventi della tua comunità locale! .info-note p strong 💡 Suggerimento: - | Se dovesse passare più di 24 ore, contatta il tuo invitante per ricordargli di ammetterti. + | Se dovessero passare più di 24 ore senza ammissione, contatta il tuo invitante per ricordargli di approvarti. + //- Footer .email-footer .divider - p Hai ricevuto questa email perché ti sei registrato su #{nomeapp || 'la nostra piattaforma'} - p(style="margin-top: 12px; font-size: 12px;") - | © #{new Date().getFullYear()} #{nomeapp || ''}. + p Hai ricevuto questa email perché ti sei registrato su #{nomeapp || 'RISO'} + p(style="margin-top: 12px; font-size: 12px;") + | #{new Date().getFullYear()} #{nomeapp || 'RISO'} - Rete Italiana Scambi Orizzontali p(style="margin-top: 8px; font-size: 11px; color: #999;") - | Se non hai richiesto questa registrazione, ignora questa email. \ No newline at end of file + | Se non hai richiesto questa registrazione, puoi semplicemente ignorare questa email. + p(style="margin-top: 12px; font-size: 12px;") + | 🍚 Comunità · Fiducia · Scambi Solidali · Sostenibilità \ No newline at end of file diff --git a/emails/resetpwd/it/html.pug b/emails/resetpwd/it/html.pug index a9a0d56..6d4bdf7 100755 --- a/emails/resetpwd/it/html.pug +++ b/emails/resetpwd/it/html.pug @@ -1,26 +1,128 @@ -p Ciao #{name}, -p #{nomeapp} recentemente ha ricevuto una richiesta per una password dimenticata. - -p Per cambiare la tua password di #{nomeapp} -p Clicca QUI -span Oppure inserisci il codice -span.grande #{tokenforgot_code} -span sulla APP -p -p P.S: Se non sei stato tu a richiedere questo cambiamento, non hai bisogno di fare niente. -p Questo link scadrà tra 4 ore.
- -p Cordiali Saluti -p Supporto #{nomeapp} - -style(type="text/css"). - html, body { - padding: 0; - margin: 0; - } - - .grande { - font-size: 1.25rem; - font-weight: bold; - } - +doctype html +html(lang="it") + head + meta(charset="UTF-8") + meta(name="viewport" content="width=device-width, initial-scale=1.0") + title Recupera Password - #{nomeapp} + + body(style="margin: 0; padding: 0; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); background-color: #f5f7fa;") + + // Container Principale + table(role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%" style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); padding: 40px 20px;") + tr + td(align="center") + + // Card Email + table(role="presentation" cellspacing="0" cellpadding="0" border="0" width="600" style="max-width: 600px; background: #ffffff; border-radius: 24px; box-shadow: 0 8px 32px rgba(0, 0, 0, 0.16); overflow: hidden;") + + // Header con Icona + tr + td(style="background: linear-gradient(to bottom, rgba(103, 126, 234, 0.08), transparent); padding: 40px 32px 32px; text-align: center; border-bottom: 1px solid rgba(0, 0, 0, 0.06);") + table(role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%") + tr + td(align="center") + // Icona + div(style="width: 100px; height: 100px; margin: 0 auto 20px; background: linear-gradient(135deg, rgba(25, 118, 210, 0.15), rgba(38, 166, 154, 0.15)); border-radius: 50%; display: flex; align-items: center; justify-content: center;") + span(style="font-size: 48px; color: #1976d2;") 🔐 + + // Titolo + h1(style="margin: 0 0 12px; font-size: 28px; font-weight: 600; color: #1a1a1a; line-height: 1.3;") Recupera la tua Password + p(style="margin: 0; font-size: 16px; color: #666; line-height: 1.5;") + | Ciao + strong(style="color: #333;") #{name} + | , abbiamo ricevuto una richiesta per reimpostare la tua password + + // Contenuto Principale + tr + td(style="padding: 32px;") + + // Messaggio + p(style="margin: 0 0 24px; font-size: 16px; color: #333; line-height: 1.6;") + | Per cambiare la tua password di + strong #{nomeapp} + | , puoi utilizzare uno dei seguenti metodi: + + // Metodo 1: Bottone Link + table(role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%" style="margin-bottom: 32px;") + tr + td(style="background: linear-gradient(to right, rgba(25, 118, 210, 0.08), transparent); padding: 24px; border-radius: 16px; border: 1px solid rgba(25, 118, 210, 0.15);") + p(style="margin: 0 0 16px; font-size: 14px; font-weight: 600; color: #1976d2; text-transform: uppercase; letter-spacing: 0.5px;") ✨ Metodo 1: Link Diretto + + // Bottone CTA + table(role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%") + tr + td(align="center" style="padding: 8px 0;") + a(href=strlinksetpassword target="_blank" style="display: inline-block; padding: 16px 48px; background: linear-gradient(135deg, #1976d2, #42a5f5); color: #ffffff; text-decoration: none; border-radius: 12px; font-size: 16px; font-weight: 600; box-shadow: 0 4px 16px rgba(25, 118, 210, 0.3);") + | 🔓 Reimposta Password + + p(style="margin: 16px 0 0; font-size: 13px; color: #666; text-align: center;") + | Il link è valido per + strong(style="color: #f2c037;") 4 ore + + // Divisore + table(role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%" style="margin: 24px 0;") + tr + td(style="position: relative; text-align: center;") + div(style="position: relative; height: 1px; background: linear-gradient(to right, transparent, rgba(0, 0, 0, 0.12), transparent);") + span(style="position: relative; top: -12px; display: inline-block; padding: 4px 16px; background: #ffffff; color: #666; font-size: 14px; font-weight: 500; border-radius: 12px; border: 1px solid rgba(0, 0, 0, 0.08);") oppure + + // Metodo 2: Codice + table(role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%" style="margin-bottom: 24px;") + tr + td(style="background: linear-gradient(to right, rgba(33, 186, 69, 0.08), transparent); padding: 24px; border-radius: 16px; border: 1px solid rgba(33, 186, 69, 0.15);") + p(style="margin: 0 0 16px; font-size: 14px; font-weight: 600; color: #21ba45; text-transform: uppercase; letter-spacing: 0.5px;") 🔢 Metodo 2: Codice di Verifica + + p(style="margin: 0 0 12px; font-size: 15px; color: #333;") Inserisci questo codice nell'app: + + // Codice Box + div(style="background: #ffffff; border: 2px dashed #21ba45; border-radius: 12px; padding: 20px; text-align: center; margin: 16px 0;") + div(style="font-size: 36px; font-weight: 700; color: #1976d2; letter-spacing: 8px; font-family: 'Courier New', monospace;") #{tokenforgot_code} + + p(style="margin: 12px 0 0; font-size: 13px; color: #666; text-align: center;") + | Copia e incolla il codice nell'app per confermare + + // Warning Box + table(role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%") + tr + td(style="background: rgba(242, 192, 55, 0.1); padding: 16px; border-radius: 12px; border-left: 4px solid #f2c037;") + p(style="margin: 0; font-size: 14px; color: #666; line-height: 1.6;") + strong(style="color: #333;") ⚠️ Importante: + br + | Se non sei stato tu a richiedere questo cambiamento, ignora questa email. La tua password rimarrà invariata. + + // Footer + tr + td(style="background: linear-gradient(to top, rgba(0, 0, 0, 0.02), transparent); padding: 32px; text-align: center; border-top: 1px solid rgba(0, 0, 0, 0.06);") + p(style="margin: 0 0 8px; font-size: 15px; color: #333; font-weight: 600;") Cordiali Saluti + p(style="margin: 0 0 20px; font-size: 15px; color: #1976d2; font-weight: 600;") + | Supporto #{nomeapp} + + // Info Footer + p(style="margin: 0; font-size: 13px; color: #999; line-height: 1.6;") + | Questa è una email automatica, per favore non rispondere. + br + | © #{new Date().getFullYear()} #{nomeapp}. Tutti i diritti riservati. + + // Versione Mobile (per client email che non supportano media queries) + table(role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%" style="max-width: 600px; margin: 0 auto; display: none;") + tr + td + style(type="text/css"). + @media only screen and (max-width: 600px) { + table[class="mobile-responsive"] { + width: 100% !important; + } + + td[class="mobile-padding"] { + padding: 20px 16px !important; + } + + h1 { + font-size: 24px !important; + } + + .code-box { + font-size: 28px !important; + letter-spacing: 4px !important; + } + } diff --git a/filelog.txt b/filelog.txt index e2ddb18..d813f3d 100644 --- a/filelog.txt +++ b/filelog.txt @@ -78,3 +78,7 @@ 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 + +Lun 24/11 ORE 13:56: USER [perseo7]: ciao + +Lun 24/11 ORE 13:57: USER [perseo7]: chi sono diff --git a/src/locales/back/it.json b/src/locales/back/it.json index 48621d3..3fa755a 100755 --- a/src/locales/back/it.json +++ b/src/locales/back/it.json @@ -5,4 +5,7 @@ "Nuova Registrazione": "Nuova Registrazione", "Effettuata una Nuova Registrazione": "Effettuata una Nuova Registrazione", "partecipanti": "partecipanti", + "Il membro ": "Il membro ", + " è stato già Ammesso!": " è stato già Ammesso!", + "Ottimo! Hai ammesso ": "Ottimo! Hai ammesso " } diff --git a/src/models/user.js b/src/models/user.js index 1f57800..91c6c8a 100755 --- a/src/models/user.js +++ b/src/models/user.js @@ -202,6 +202,12 @@ const UserSchema = new mongoose.Schema({ verified_by_aportador: { type: Boolean, }, + token_da_ammettere: { + type: String, + }, + date_token_ammettere: { + type: Date, + }, notask_verif: { type: Boolean, }, @@ -1624,6 +1630,57 @@ UserSchema.statics.setUserQualified = async function (idapp, username) { return !!myrec; }; +UserSchema.statics.setAmmissioneByTokenAndUsername = async function (idapp, username) { + const User = this; + + try { + + if (username === undefined) return false; + + const myquery = { + idapp: idapp, + username: username, + }; + + let creatoken = true; + let token = ''; + + const recfound = await User.findOne(myquery, { verified_by_aportador: 1, username: 1, token_da_ammettere: 1 }); + if (recfound) { + if (recfound.token_da_ammettere) { + // token già creato + creatoken = false; + token = recfound.token_da_ammettere; + } + } + + if (creatoken) { + token = tools.getTokenRandom(); + } else { + return recfound; + } + + const rec = await User.findOneAndUpdate(myquery, { $set: { token_da_ammettere: token, date_token_ammettere: new Date(), } }, { new: true }); + return rec; + } catch (e) { + console.error('Error setAmmissione', e); + } +}; + +UserSchema.statics.findAmmissioneByTokenAndUsername = async function (idapp, token, username) { + const User = this; + + if (username === undefined) return false; + + const myquery = { + idapp: idapp, + token_da_ammettere: token, + }; + + const rec = await User.findOne(myquery, { verified_by_aportador: 1, username: 1, aportador_solidario: 1, idapp: 1, lang: 1 }); + return rec && username.toLowerCase() === rec.username.toLowerCase() ? rec : null; +}; + UserSchema.statics.setVerifiedByAportador = async function (idapp, username, valuebool) { const User = this; diff --git a/src/modules/CronMod.js b/src/modules/CronMod.js index d525c9e..cca5f6a 100644 --- a/src/modules/CronMod.js +++ b/src/modules/CronMod.js @@ -178,29 +178,6 @@ class CronMod { } ris = { num }; - /*} else if (mydata.dbop === 'visuPlacca') { - - mystr = '✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨\n' + - 'NAVI CHE SALPANO DALLA ' + mydata.riga + '.' + mydata.col + ' ALLA ' + mydata.riga + '.' + (parseInt(mydata.col) + 7) + '\n' + - 'AUGURI ALLA NUOVA SOGNATRICE !!!\n' + - '✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨'; - - const visu_nave_Bot = await Settings.getValDbSettings(idapp, 'VISU_NAVE_BOT'); - - for (let ind = 0; ind < 8; ind++) { - mystr += await Nave.getNavePos(idapp, parseInt(mydata.riga), parseInt(mydata.col) + ind, false); - mystr += tools.ACAPO; - if (visu_nave_Bot && ind === 3) { - await telegrambot.sendMsgTelegramToTheAdmin(idapp, mystr, true); - mystr = ''; - } - } - - if (visu_nave_Bot) - await telegrambot.sendMsgTelegramToTheAdmin(idapp, mystr, true); - - ris = { mystr }; - */ } else if (mydata.dbop === 'CorreggiTabHours') { ris = await Hours.correggiHours(idapp); } else if (mydata.dbop === 'setVerifiedByAportadorToALL') { diff --git a/src/modules/dist/CronMod.dev.js b/src/modules/dist/CronMod.dev.js index a947659..c82c9c3 100644 --- a/src/modules/dist/CronMod.dev.js +++ b/src/modules/dist/CronMod.dev.js @@ -293,25 +293,6 @@ function () { ris = { num: num }; - /*} else if (mydata.dbop === 'visuPlacca') { - mystr = '✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨\n' + - 'NAVI CHE SALPANO DALLA ' + mydata.riga + '.' + mydata.col + ' ALLA ' + mydata.riga + '.' + (parseInt(mydata.col) + 7) + '\n' + - 'AUGURI ALLA NUOVA SOGNATRICE !!!\n' + - '✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨'; - const visu_nave_Bot = await Settings.getValDbSettings(idapp, 'VISU_NAVE_BOT'); - for (let ind = 0; ind < 8; ind++) { - mystr += await Nave.getNavePos(idapp, parseInt(mydata.riga), parseInt(mydata.col) + ind, false); - mystr += tools.ACAPO; - if (visu_nave_Bot && ind === 3) { - await telegrambot.sendMsgTelegramToTheAdmin(idapp, mystr, true); - mystr = ''; - } - } - if (visu_nave_Bot) - await telegrambot.sendMsgTelegramToTheAdmin(idapp, mystr, true); - ris = { mystr }; - */ - _context.next = 682; break; diff --git a/src/router/index_router.js b/src/router/index_router.js index fe12bdf..6943da7 100755 --- a/src/router/index_router.js +++ b/src/router/index_router.js @@ -5,10 +5,13 @@ const router = express.Router(), const telegrambot = require('../telegram/telegrambot'); + const i18n = require('i18n'); const sharp = require('sharp'); +const printf = require('util').format; + const { authenticate, authenticate_noerror, @@ -124,6 +127,78 @@ const UserCost = { ], }; +router.post('/ammetti', (req, res) => { + const body = _.pick(req.body, ['idapp', 'token', 'username']); + const idapp = body.idapp; + const token = body.token; + const username = body.username; + + try { + // Cerco il token se è ancora da ammettere + + User.findAmmissioneByTokenAndUsername(idapp, token, username) + .then(async (user) => { + if (!user) { + return res.status(404).send(); + } else { + const lang = user.lang; + console.log('user', user); + user.verified_by_aportador = false; + if (user.verified_by_aportador) { + res.send({ + code: server_constants.RIS_CODE_GIA_AMMESSO, + msg: 'Il membro ' + user.username + ' è stato già Ammesso!', + }); + } else { + user.verified_by_aportador = true; + + const userDest = await User.getUserShortDataByUsername(user.idapp, user.aportador_solidario); + const myuser = user; + const dati = { + token, + } + + const msgOrig = i18n.__( + { phrase: '✅ Sei stato Ammesso correttamente da %s!', locale: lang }, + userDest.username + ); + const msgDest = i18n.__( + { phrase: '✅ %s è stato Ammesso correttamente (da %s)!', locale: lang }, + myuser.username, + userDest.username + ); + + const sendemail = require('../sendemail'); + + // Invia una email alla persona che è stata ammessa + const ris = await sendemail.sendEmail_Utente_Ammesso(user.lang, userDest.email, userDest, user.idapp, dati); + + await telegrambot.sendMsgTelegram(user.idapp, myuser.username, msgOrig); + await telegrambot.sendMsgTelegram(user.idapp, userDest.username, msgDest); + // Invia questo msg anche all'Admin + await telegrambot.sendMsgTelegramToTheAdmin(user.idapp, msgDest, userDest.username); + + // user.token_da_ammettere = 'OK'; + user.save().then(() => { + res.send({ + code: server_constants.RIS_CODE_AMMESSO, + msg: 'Ottimo! Hai ammesso ' + user.username + '!', + //msg: tools.getres__('Ottimo! Hai ammesso', res) + ' ' + user.username + '!', + }); + }); + } + } + }) + .catch((e) => { + console.log('Errore Ammissione:', e.message); + res.status(400).send(); + }); + } catch (e) { + console.error('Errore: ', e); + res.status(400).send(); + } +}); + router.post(process.env.LINKVERIF_REG, (req, res) => { const body = _.pick(req.body, ['idapp', 'idlink']); const idapp = body.idapp; @@ -335,7 +410,9 @@ router.post('/sendmailreg', authenticate, async (req, res) => { const diffMinutes = Math.ceil(diffTime / (1000 * 60)); if (diffMinutes < 5) { - return res.status(200).send({ email_inviata: false, error: 'Attendi qualche minuto prima di reinviare nuovamente.' }); + return res + .status(200) + .send({ email_inviata: false, error: 'Attendi qualche minuto prima di reinviare nuovamente.' }); } ris = await sendemail.sendEmail_Registration(user.lang, user.email, user, user.idapp, user.linkreg); user.lasttime_email_sent_verify = now; @@ -396,7 +473,9 @@ router.post('/settable', authenticate, async (req, res) => { (await !tools.ModificheConsentite(req, params.table, fieldsvalue, mydata ? mydata._id : '')) ) { // If without permissions, exit - 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: '' }); } if (shared_consts.TABLES_USER_ID.includes(params.table)) { @@ -533,7 +612,6 @@ router.post('/settable', authenticate, async (req, res) => { } } - return await myPromise .then(async (doupdate) => { if (false) { @@ -827,7 +905,9 @@ router.post('/getexp', authenticate, (req, res) => { if (!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: '' }); + return res + .status(server_constants.RIS_CODE_ERR_UNAUTHORIZED) + .send({ code: server_constants.RIS_CODE_ERR_UNAUTHORIZED, msg: '' }); } try { @@ -1334,7 +1414,9 @@ router.patch('/chval', authenticate, async (req, res) => { !(mydata.table === 'accounts' && (await Account.canEditAccountAdmins(req.user.username, mydata.id))) ) { // If without permissions, exit - 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 camporequisiti = UserCost.FIELDS_REQUISITI.includes(Object.keys(fieldsvalue)[0]); @@ -1617,7 +1699,9 @@ router.patch('/askfunz', authenticate, async (req, res) => { req.user._id.toString() !== id ) { // If without permissions, exit - 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: '' }); } } @@ -1676,7 +1760,9 @@ router.patch('/callfunz', authenticate, async (req, res) => { req.user._id.toString() !== id ) { // If without permissions, exit - 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: '' }); } } @@ -1755,7 +1841,9 @@ router.delete('/delrec/:table/:id', authenticate, async (req, res) => { (await !tools.ModificheConsentite(req, tablename, fields, id, req.user)) ) { // If without permissions, exit - 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: '' }); } let cancellato = false; @@ -1863,7 +1951,9 @@ router.post('/duprec/:table/:id', authenticate, async (req, res) => { const mytable = globalTables.getTableByTableName(tablename); if (!req.user) { - 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: '' }); } /* if (!User.isAdmin(req.user.perm) && !User.isManager(req.user.perm)) { diff --git a/src/router/invitaAmicoRoutes.js b/src/router/invitaAmicoRoutes.js index a23375f..2c95411 100644 --- a/src/router/invitaAmicoRoutes.js +++ b/src/router/invitaAmicoRoutes.js @@ -140,7 +140,7 @@ router.post('/invia-email', authenticate, async (req, res) => { }); await listainviti.save(); - + const ris = await sendemail.sendEmail_InvitaAmico('it', emailAmico, null, idapp, dati); if (ris) { diff --git a/src/sendemail.js b/src/sendemail.js index 15923a4..c08e40d 100755 --- a/src/sendemail.js +++ b/src/sendemail.js @@ -498,9 +498,16 @@ module.exports = { const strlinkreg = tools.getHostByIdApp(idapp) + `/invitetoreg/${dati.token}`; return strlinkreg; }, + getLinkAmmissione: function (idapp, user) { + if (user.token_da_ammettere) { + const strlink = tools.getHostByIdApp(idapp) + `/ammetti/${user.token_da_ammettere}/${user.username}`; + return strlink; + } + return ''; + }, getPathEmail(idapp, email_template) { - const RISO_TEMPLATES = ['reg_notifica_all_invitante', 'reg_email_benvenuto_ammesso']; + const RISO_TEMPLATES = ['reg_notifica_all_invitante', 'reg_email_benvenuto_ammesso', 'reg_chiedi_ammettere_all_invitante']; if (idapp === '13') { if (RISO_TEMPLATES.includes(email_template)) { @@ -513,6 +520,14 @@ module.exports = { try { const nomecognomeInvitante = await User.getNameSurnameByUsername(idapp, user.aportador_solidario, true); + if (!user.verified_by_aportador) { + // Genera Token per Ammettere l'Utente + const r1 = await User.setAmmissioneByTokenAndUsername(idapp, user.username); + if (r1 && r1.token_da_ammettere) { + user.token_da_ammettere = r1.token_da_ammettere; + } + } + let mylocalsconf = { idapp, dataemail: await this.getdataemail(idapp), @@ -522,6 +537,7 @@ module.exports = { strlinksito: tools.getHostByIdApp(idapp), strlinkreg: this.getlinkReg(idapp, idreg), forgetpwd: tools.getHostByIdApp(idapp) + '/requestresetpwd', + linkAmmissione: this.getLinkAmmissione(idapp, user), emailto: emailto, verified_email: user.verified_email, usernameInvitante: user.aportador_solidario, @@ -547,7 +563,7 @@ module.exports = { //Invia una email al nuovo utente await this.sendEmail_base(quale_email_inviare, emailto, mylocalsconf, tools.getreplyToEmailByIdApp(idapp)); - if (user.verified_email && user.aportador_solidario) { + if (user.verified_email && user.aportador_solidario && user.verified_by_aportador) { const pathemail = this.getPathEmail(idapp, 'reg_notifica_all_invitante'); // Manda anche una email al suo Invitante @@ -558,6 +574,17 @@ module.exports = { mylocalsconf, '' ); + } else if (user.aportador_solidario && !user.verified_by_aportador) { + const pathemail = this.getPathEmail(idapp, 'reg_chiedi_ammettere_all_invitante'); + + // Manda una email al suo Invitante per chiedere di essere ammesso + const recaportador = await User.getUserShortDataByUsername(idapp, user.aportador_solidario); + const ris = await this.sendEmail_base( + pathemail + '/' + tools.LANGADMIN, + recaportador.email, + mylocalsconf, + '' + ); } // Send to the Admin an Email @@ -626,15 +653,18 @@ module.exports = { emailto: emailto, usernameInvitante: dati.usernameInvitante, ammessoUtente: true, + user, }; - const ris = await this.sendEmail_base('reg_email_benvenuto_ammesso/' + lang, emailto, mylocalsconf, ''); + const quale_email_inviare = this.getPathEmail(idapp, 'reg_email_benvenuto_ammesso') + '/' + lang; + + const ris = await this.sendEmail_base(quale_email_inviare, emailto, mylocalsconf, ''); await telegrambot.notifyToTelegram(telegrambot.phase.AMMETTI_UTENTE, mylocalsconf); return ris; } catch (e) { - console.error('Err sendEmail_InvitaAmico', e); + console.error('Err sendEmail_Utente_Ammesso', e); } }, diff --git a/src/telegram/telegrambot.js b/src/telegram/telegrambot.js index ed0d079..8192a74 100644 --- a/src/telegram/telegrambot.js +++ b/src/telegram/telegrambot.js @@ -36,6 +36,8 @@ const { MsgTemplate } = require('../models/msg_template'); const i18n = require('i18n'); + + let url = process.env.URL || 'https://'; const Benvenuto = '💓💓💓 Benvenuto/a!'; @@ -916,6 +918,7 @@ const MyTelegramBot = { callback_data: InlineConferma.RISPOSTA_SI + myfunc + tools.SEP + myuser.username + tools.SEP + userDest, }, ]); + } /*{ text: '🚫 Rifiuta ' + myuser.username, @@ -927,7 +930,6 @@ const MyTelegramBot = { if (telegid > 0) { cl.setPhotoProfile(myuser, telegid, false); - const rismsg = await MsgTemplate.getMsgByLang( idapp, myuser, @@ -941,7 +943,6 @@ const MyTelegramBot = { userDest = myuser.aportador_solidario; let useraportador = await User.getUserShortDataByUsername(idapp, userDest); - const rismsg2 = await MsgTemplate.getMsgByLang( idapp, myuser, @@ -949,7 +950,6 @@ const MyTelegramBot = { myuser.lang ); - const telegidInvitante = useraportador.profile.teleg_id; await cl.sendMsgLog(telegidInvitante, rismsg2.body); @@ -1114,7 +1114,6 @@ const MyTelegramBot = { } }, - askConfirmationUserFriend: async function (idapp, myfunc, myuser, userDest = '', username = '') { try { const cl = getclTelegByidapp(idapp); @@ -2986,13 +2985,6 @@ class Telegram { if (recuser) { rec.user = recuser; console.log(recuser.username, " SI E' VERIFICATO CON TELEGRAM !"); - // let username = recuser.name; - - /*if (!!msg.from.username) { - await MyTelegramBot.askConfirmationUser(this.idapp, shared_consts.CallFunz.REGISTRATION, recuser); - } else { - console.log(' ... MA GLI MANCA L\'USERNAME TELEGRAM !! '); - } */ } } } @@ -3318,7 +3310,6 @@ class Telegram { await this.verificaTelegramCompleted(msg, recuser); } } - } } @@ -3335,7 +3326,6 @@ class Telegram { msg.from.last_name || '' ); - rec.status = Status.VERIFIED; rec.datemenu_updated = null; rec.menuDb = null; @@ -4486,6 +4476,8 @@ if (true) { // RISPOSTE ALLE CALLBACK (Bottoni) + const sendemail = require('../sendemail'); + let testo_notifica_di_risposta = ''; try { @@ -4578,6 +4570,7 @@ if (true) { ); // Invia una email alla persona che è stata ammessa + const ris = await sendemail.sendEmail_Utente_Ammesso(user.lang, userDest, null, user.idapp, null); 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 a3c19aa..1236923 100755 --- a/src/tools/general.js +++ b/src/tools/general.js @@ -96,6 +96,8 @@ const textlang = { NON_VERIF: 'Non Verificata', VERIF: 'Verificata', EMAIL: 'Email', + MEMBRO_AMMESSO: 'Ottimo! Hai ammesso %s!', + MEMBRO_GIA_AMMESSO: 'Il membro %s è stato già Ammesso!', BOT: 'BOT', EMAIL_NON_VERIF: 'Email Non Verificata\nleggi la tua casella email e trova **"Confermare la Registrazione"**\ne clicca sul bottone **"Verifica Registrazione"**', diff --git a/src/tools/server_constants.js b/src/tools/server_constants.js index d7a5f14..2724041 100755 --- a/src/tools/server_constants.js +++ b/src/tools/server_constants.js @@ -6,6 +6,9 @@ module.exports = Object.freeze({ RIS_CODE_EMAIL_ALREADY_VERIFIED: -5, RIS_CODE_EMAIL_VERIFIED: 1, + RIS_CODE_AMMESSO: 1, + RIS_CODE_GIA_AMMESSO: -5, + RIS_CODE_REC_DUPLICATED_DESCR_CITY_USER: -110, RIS_CODE_REC_ALREADY_EXIST_SYMBOL: -102, RIS_CODE_REC_ALREADY_EXIST_CODE: -101, @@ -31,7 +34,7 @@ module.exports = Object.freeze({ RIS_CODE_HTTP_INVALID_TOKEN: 401, RIS_CODE_HTTP_FORBIDDEN_PERMESSI: 403, RIS_CODE_HTTP_TOKEN_EXPIRED: 408, - + RIS_CODE_TOKEN_RESETPASSWORD_NOT_FOUND: -23, RIS_SUBSCRIBED_OK: 1, @@ -53,30 +56,30 @@ module.exports = Object.freeze({ es: 'Suscripción al boletín confirmado!', it: 'Sottoscrizione alla Newsletter Confermata!', fr: 'Inscription à la newsletter confirmée!', - de: 'Anmeldung zum Newsletter bestätigt!' - } , + de: 'Anmeldung zum Newsletter bestätigt!', + }, RIS_SUBSCRIBED_MSG_ALREADYEXIST: { enUs: 'Subscription already made!', es: 'Suscripción ya realizada!', it: 'Sottoscrizione già effettuata!', fr: 'Abonnement déjà fait!', - de: 'Abonnement bereits gemacht!' - } , + de: 'Abonnement bereits gemacht!', + }, RIS_SUBSCRIBED_MSG_FAILED: { enUs: 'Sign Up Failed :(', es: 'Suscripción al boletín fallido', it: 'Sottoscrizione alla Newsletter Fallita', fr: 'Abonnement à la newsletter en échec', de: 'Abonnement des fehlgeschlagenen Newsletters', - } , + }, RIS_UNSUBSTR_NOT_EXIST: { enUs: 'Subscription email not found!', es: 'Suscripción email no encontrada!', it: 'Sottoscrizione Email non trovata!', fr: 'Abonnement courriel introuvable!', - de: 'E-Mail-Abonnement nicht gefunden!' - } , + de: 'E-Mail-Abonnement nicht gefunden!', + }, RIS_UNSUB_ERROR_FAILED: { enUs: 'Unsubscribed Failed :(', @@ -84,16 +87,15 @@ module.exports = Object.freeze({ it: 'Desottoscrizione alla Newsletter Fallita', fr: 'Désabonnement à la newsletter en échec', de: 'Abmeldung des fehlgeschlagenen Newsletters', - } , + }, RIS_UNSUBSCRIBED_MSG_ALREADY_DONE: { enUs: 'Unsubscription already made!', es: 'Unsuscripción ya realizada!', it: 'Desottoscrizione già effettuata!', fr: 'Désabonnement déjà fait!', - de: 'Abmeldung bereits gemacht!' - } , - + de: 'Abmeldung bereits gemacht!', + }, LIST_END: '10000000', LIST_START: null, @@ -101,7 +103,7 @@ module.exports = Object.freeze({ PREFIX_IMG: 'm_', PREFIX_IMG_SMALL: 'sm_', - DIR_UPLOAD: '/upload', //'/upload' + DIR_UPLOAD: '/upload', //'/upload' DIR_PUBLIC_LOCALE: '/public', Privacy: { @@ -109,7 +111,7 @@ module.exports = Object.freeze({ friends: 'friends', mygroup: 'mygroup', onlyme: 'onlyme', - inherited: 'inherited' + inherited: 'inherited', }, TypeProj: { @@ -117,13 +119,7 @@ module.exports = Object.freeze({ TYPE_SUBDIR: 2, }, - User_Fields: [ - 'name', - 'surname', - 'news_on', - 'profile', - ], + User_Fields: ['name', 'surname', 'news_on', 'profile'], FILECONFIG_SERVER: 'lists_serverconfig.txt', - });