- verifica email se non è stata verificata (componente)
- altri aggiornamenti grafica PAGERIS. - OLLAMA AI
This commit is contained in:
@@ -39,3 +39,5 @@ AUTH_NEW_SITES=123123123
|
|||||||
SCRIPTS_DIR=admin_scripts
|
SCRIPTS_DIR=admin_scripts
|
||||||
CLOUDFLARE_TOKENS=[{"label":"Paolo.arena77@gmail.com","value":"M9EM309v8WFquJKpYgZCw-TViM2wX6vB3wlK6GD0"},{"label":"gruppomacro.com","value":"bqmzGShoX7WqOBzkXocoECyBkPq3GfqcM5t6VFd8"}]
|
CLOUDFLARE_TOKENS=[{"label":"Paolo.arena77@gmail.com","value":"M9EM309v8WFquJKpYgZCw-TViM2wX6vB3wlK6GD0"},{"label":"gruppomacro.com","value":"bqmzGShoX7WqOBzkXocoECyBkPq3GfqcM5t6VFd8"}]
|
||||||
DS_API_KEY="sk-222e3addb3d8455d8b0516d93906eec7"
|
DS_API_KEY="sk-222e3addb3d8455d8b0516d93906eec7"
|
||||||
|
OLLAMA_URL=http://localhost:11434
|
||||||
|
OLLAMA_DEFAULT_MODEL=llama3.2:3b
|
||||||
404
emails/defaultSite/reg_resend_email_to_verifiyng/it/html.pug
Executable file
404
emails/defaultSite/reg_resend_email_to_verifiyng/it/html.pug
Executable file
@@ -0,0 +1,404 @@
|
|||||||
|
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, #1976D2 0%, #1565C0 100%);
|
||||||
|
color: white;
|
||||||
|
padding: 40px 24px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.email-header h1 {
|
||||||
|
margin: 0 0 8px 0;
|
||||||
|
font-size: 26px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.email-header p {
|
||||||
|
margin: 8px 0 0 0;
|
||||||
|
font-size: 16px;
|
||||||
|
opacity: 0.95;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.verification-icon {
|
||||||
|
font-size: 56px;
|
||||||
|
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: #1976D2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-message {
|
||||||
|
background: linear-gradient(135deg, #E3F2FD 0%, #BBDEFB 100%);
|
||||||
|
border-left: 4px solid #1976D2;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 20px;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-message h2 {
|
||||||
|
color: #1565C0;
|
||||||
|
font-size: 18px;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-message p {
|
||||||
|
color: #1976D2;
|
||||||
|
font-size: 15px;
|
||||||
|
line-height: 1.6;
|
||||||
|
margin: 8px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.warning-box {
|
||||||
|
background: #FFF8E1;
|
||||||
|
border-left: 4px solid #FFA000;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 16px;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.warning-box p {
|
||||||
|
color: #E65100;
|
||||||
|
font-size: 14px;
|
||||||
|
margin: 0;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.warning-box strong {
|
||||||
|
color: #BF360C;
|
||||||
|
}
|
||||||
|
|
||||||
|
.email-info-box {
|
||||||
|
background: #f8f9fa;
|
||||||
|
border-left: 4px solid #1976D2;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 16px;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.email-info-title {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #555;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.email-address {
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #1976D2;
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cta-section {
|
||||||
|
margin: 24px 0;
|
||||||
|
padding: 24px 0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cta-title {
|
||||||
|
font-size: 19px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #1a1a1a;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cta-subtitle {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #666;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cta-button {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 18px 40px;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: white;
|
||||||
|
background: linear-gradient(135deg, #1976D2 0%, #1565C0 100%);
|
||||||
|
border-radius: 50px;
|
||||||
|
text-decoration: none;
|
||||||
|
box-shadow: 0 4px 12px rgba(25, 118, 210, 0.35);
|
||||||
|
transition: transform 0.2s, box-shadow 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cta-button:hover {
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 6px 16px rgba(25, 118, 210, 0.45);
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-icon {
|
||||||
|
font-size: 20px;
|
||||||
|
margin-right: 8px;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.link-fallback {
|
||||||
|
margin-top: 20px;
|
||||||
|
padding: 16px;
|
||||||
|
background: #f5f5f5;
|
||||||
|
border-radius: 8px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.link-fallback p {
|
||||||
|
font-size: 13px;
|
||||||
|
color: #666;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.link-fallback a {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #1976D2;
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
|
||||||
|
.expiry-notice {
|
||||||
|
background: linear-gradient(135deg, #FFEBEE 0%, #FFCDD2 100%);
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 16px;
|
||||||
|
margin: 24px 0;
|
||||||
|
text-align: center;
|
||||||
|
border: 1px solid #EF9A9A;
|
||||||
|
}
|
||||||
|
|
||||||
|
.expiry-notice p {
|
||||||
|
margin: 0;
|
||||||
|
color: #C62828;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.expiry-notice strong {
|
||||||
|
color: #B71C1C;
|
||||||
|
}
|
||||||
|
|
||||||
|
.help-section {
|
||||||
|
background: #FAFAFA;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 20px;
|
||||||
|
margin: 24px 0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.help-section h3 {
|
||||||
|
font-size: 16px;
|
||||||
|
color: #333;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.help-section p {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #666;
|
||||||
|
margin: 8px 0;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.help-section a {
|
||||||
|
color: #1976D2;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.help-section a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.security-note {
|
||||||
|
background: #E8F5E9;
|
||||||
|
border-left: 4px solid #4CAF50;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 14px;
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.security-note p {
|
||||||
|
font-size: 13px;
|
||||||
|
color: #2E7D32;
|
||||||
|
margin: 0;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.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: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.email-header p {
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.email-body {
|
||||||
|
padding: 20px 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-message {
|
||||||
|
padding: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.email-address {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cta-button {
|
||||||
|
padding: 16px 32px;
|
||||||
|
font-size: 15px;
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.link-fallback a {
|
||||||
|
font-size: 11px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
body
|
||||||
|
.email-container
|
||||||
|
.email-header
|
||||||
|
- var baseimg = baseurl + '/';
|
||||||
|
h1 ✉️ Verifica il tuo indirizzo email
|
||||||
|
p Conferma la tua email per continuare a usare #{nomeapp}
|
||||||
|
|
||||||
|
.email-body
|
||||||
|
.intro-text
|
||||||
|
| Ciao
|
||||||
|
strong #{name || username}
|
||||||
|
| ! 👋
|
||||||
|
br
|
||||||
|
| Abbiamo ricevuto una richiesta per verificare nuovamente il tuo indirizzo email.
|
||||||
|
|
||||||
|
.info-message
|
||||||
|
h2 📧 Perché devo verificare di nuovo?
|
||||||
|
p Potrebbe essere perché hai cambiato email, per motivi di sicurezza, o perché la verifica precedente è scaduta.
|
||||||
|
p Questa procedura ci aiuta a mantenere sicuro il tuo account.
|
||||||
|
|
||||||
|
if emailto
|
||||||
|
.email-info-box
|
||||||
|
.email-info-title Email da verificare
|
||||||
|
.email-address #{emailto}
|
||||||
|
|
||||||
|
.cta-section
|
||||||
|
.cta-title Conferma il tuo indirizzo email
|
||||||
|
.cta-subtitle Clicca il bottone qui sotto per completare la verifica
|
||||||
|
|
||||||
|
if verifyLink
|
||||||
|
a.cta-button(href=verifyLink target="_blank")
|
||||||
|
span.button-icon ✓
|
||||||
|
| Verifica Email
|
||||||
|
|
||||||
|
.link-fallback
|
||||||
|
p Se il bottone non funziona, copia e incolla questo link nel browser:
|
||||||
|
a(href=verifyLink) #{verifyLink}
|
||||||
|
|
||||||
|
.expiry-notice
|
||||||
|
p ⏰ Questo link scadrà tra
|
||||||
|
strong 24 ore
|
||||||
|
| .
|
||||||
|
p Se non completi la verifica in tempo, dovrai richiedere un nuovo link.
|
||||||
|
|
||||||
|
.warning-box
|
||||||
|
p ⚠️
|
||||||
|
strong Non hai richiesto questa verifica?
|
||||||
|
| Ignora questa email. Il tuo account resterà al sicuro.
|
||||||
|
|
||||||
|
.security-note
|
||||||
|
p 🔒 Per la tua sicurezza: non condividere mai questo link con nessuno. Il team di #{nomeapp} non ti chiederà mai la password via email.
|
||||||
|
|
||||||
|
.help-section
|
||||||
|
h3 Hai bisogno di aiuto?
|
||||||
|
p Non riesci a verificare la tua email?
|
||||||
|
if supportEmail
|
||||||
|
p Contattaci a
|
||||||
|
a(href="mailto:" + supportEmail) #{supportEmail}
|
||||||
|
if strlinksito
|
||||||
|
p Oppure visita la nostra
|
||||||
|
a(href=strlinksito + '/supporto' target="_blank") pagina di supporto
|
||||||
|
|
||||||
|
.email-footer
|
||||||
|
.divider
|
||||||
|
p Hai ricevuto questa email perché è stata richiesta una verifica per il tuo account su #{nomeapp}
|
||||||
|
p(style="margin-top: 8px; font-size: 12px; color: #999;")
|
||||||
|
| Se non hai fatto tu questa richiesta, puoi ignorare questa email.
|
||||||
|
p(style="margin-top: 12px; font-size: 12px;")
|
||||||
|
| © #{new Date().getFullYear()} #{nomeapp}
|
||||||
1
emails/defaultSite/reg_resend_email_to_verifiyng/it/subject.pug
Executable file
1
emails/defaultSite/reg_resend_email_to_verifiyng/it/subject.pug
Executable file
@@ -0,0 +1 @@
|
|||||||
|
Verifica la tua Email - ${nomeapp}`
|
||||||
17
logtrans.txt
17
logtrans.txt
@@ -519,4 +519,19 @@ Gio 04/12 ORE 18:55: [<b>Circuito RIS Bologna</b>]: Inviate Monete da SurTest a
|
|||||||
|
|
||||||
Saldi:
|
Saldi:
|
||||||
SurTest: 0.00 RIS]
|
SurTest: 0.00 RIS]
|
||||||
ElenaEspx: 38.05 RIS]
|
ElenaEspx: 38.05 RIS]
|
||||||
|
Mar 09/12 ORE 21:36: [<b>Circuito RIS Venezia</b>]: Inviate Monete da surya1977 a amandadi 11 RIS [causale: ssss]
|
||||||
|
|
||||||
|
Saldi:
|
||||||
|
surya1977: 63.00 RIS]
|
||||||
|
amandadi: 12.00 RIS]
|
||||||
|
Mer 10/12 ORE 16:18: [<b>Circuito RIS Venezia</b>]: Inviate Monete da surya1977 a amandadi 12 RIS [causale: Ciaoo]
|
||||||
|
|
||||||
|
Saldi:
|
||||||
|
surya1977: 51.00 RIS]
|
||||||
|
amandadi: 24.00 RIS]
|
||||||
|
Mer 10/12 ORE 17:02: [<b>Circuito RIS Venezia</b>]: Inviate Monete da surya1977 a amandadi 52 RIS [causale: Ancora test]
|
||||||
|
|
||||||
|
Saldi:
|
||||||
|
surya1977: -1.00 RIS]
|
||||||
|
amandadi: 76.00 RIS]
|
||||||
@@ -33,6 +33,7 @@
|
|||||||
"email-templates": "^12.0.2",
|
"email-templates": "^12.0.2",
|
||||||
"entities": "^7.0.0",
|
"entities": "^7.0.0",
|
||||||
"express": "^4.21.2",
|
"express": "^4.21.2",
|
||||||
|
"express-rate-limit": "^7.1.5",
|
||||||
"fast-csv": "^5.0.5",
|
"fast-csv": "^5.0.5",
|
||||||
"formidable": "^3.5.2",
|
"formidable": "^3.5.2",
|
||||||
"fs-extra": "^11.3.2",
|
"fs-extra": "^11.3.2",
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ var file = `.env.${node_env}`;
|
|||||||
|
|
||||||
// GLOBALI (Uguali per TUTTI)
|
// GLOBALI (Uguali per TUTTI)
|
||||||
process.env.LINKVERIF_REG = '/vreg';
|
process.env.LINKVERIF_REG = '/vreg';
|
||||||
|
process.env.CHECKREVERIF_EMAIL = '/reverif_email';
|
||||||
process.env.LINK_REQUEST_NEWPASSWORD = '/requestnewpwd';
|
process.env.LINK_REQUEST_NEWPASSWORD = '/requestnewpwd';
|
||||||
process.env.ADD_NEW_SITE = '/addNewSite';
|
process.env.ADD_NEW_SITE = '/addNewSite';
|
||||||
process.env.LINK_UPDATE_PASSWORD = '/updatepassword';
|
process.env.LINK_UPDATE_PASSWORD = '/updatepassword';
|
||||||
|
|||||||
@@ -342,8 +342,12 @@ MovementSchema.statics.getQueryMovsByCircuitId = async function (idapp, username
|
|||||||
'circuitfrom.symbol': 1,
|
'circuitfrom.symbol': 1,
|
||||||
'circuitto.symbol': 1,
|
'circuitto.symbol': 1,
|
||||||
'userfrom.verified_by_aportador': 1,
|
'userfrom.verified_by_aportador': 1,
|
||||||
|
'userfrom.name': 1,
|
||||||
|
'userfrom.surname': 1,
|
||||||
'userfrom.username': 1,
|
'userfrom.username': 1,
|
||||||
'userfrom.profile.img': 1,
|
'userfrom.profile.img': 1,
|
||||||
|
'userto.name': 1,
|
||||||
|
'userto.surname': 1,
|
||||||
'userto.username': 1,
|
'userto.username': 1,
|
||||||
'userto.profile.img': 1,
|
'userto.profile.img': 1,
|
||||||
'userto.verified_by_aportador': 1,
|
'userto.verified_by_aportador': 1,
|
||||||
@@ -579,7 +583,11 @@ MovementSchema.statics.getQueryAllUsersMovsByCircuitId = async function (idapp,
|
|||||||
'circuitfrom.symbol': 1,
|
'circuitfrom.symbol': 1,
|
||||||
'circuitto.symbol': 1,
|
'circuitto.symbol': 1,
|
||||||
'userfrom.username': 1,
|
'userfrom.username': 1,
|
||||||
|
'userfrom.name': 1,
|
||||||
|
'userfrom.surname': 1,
|
||||||
'userfrom.profile.img': 1,
|
'userfrom.profile.img': 1,
|
||||||
|
'userto.name': 1,
|
||||||
|
'userto.surname': 1,
|
||||||
'userto.username': 1,
|
'userto.username': 1,
|
||||||
'userto.profile.img': 1,
|
'userto.profile.img': 1,
|
||||||
'groupfrom.groupname': 1,
|
'groupfrom.groupname': 1,
|
||||||
@@ -1013,7 +1021,11 @@ MovementSchema.statics.getLastN_Transactions = async function (
|
|||||||
'circuitto.name': 1,
|
'circuitto.name': 1,
|
||||||
'userfrom.verified_by_aportador': 1,
|
'userfrom.verified_by_aportador': 1,
|
||||||
'userfrom.username': 1,
|
'userfrom.username': 1,
|
||||||
|
'userfrom.name': 1,
|
||||||
|
'userfrom.surname': 1,
|
||||||
'userfrom.profile.img': 1,
|
'userfrom.profile.img': 1,
|
||||||
|
'userto.name': 1,
|
||||||
|
'userto.surname': 1,
|
||||||
'userto.username': 1,
|
'userto.username': 1,
|
||||||
'userto.profile.img': 1,
|
'userto.profile.img': 1,
|
||||||
'userto.verified_by_aportador': 1,
|
'userto.verified_by_aportador': 1,
|
||||||
|
|||||||
@@ -56,6 +56,9 @@ const UserSchema = new mongoose.Schema(
|
|||||||
message: '{VALUE} is not a valid email'
|
message: '{VALUE} is not a valid email'
|
||||||
}*/
|
}*/
|
||||||
},
|
},
|
||||||
|
link_verif_email: {
|
||||||
|
type: String,
|
||||||
|
},
|
||||||
hash: {
|
hash: {
|
||||||
type: String,
|
type: String,
|
||||||
},
|
},
|
||||||
@@ -2614,6 +2617,12 @@ UserSchema.statics.removeBookmark = async function (idapp, username, id, tab) {
|
|||||||
UserSchema.statics.addBookmark = async function (idapp, username, id, tab) {
|
UserSchema.statics.addBookmark = async function (idapp, username, id, tab) {
|
||||||
return await User.updateOne({ idapp, username }, { $push: { 'profile.bookmark': { id, tab } } });
|
return await User.updateOne({ idapp, username }, { $push: { 'profile.bookmark': { id, tab } } });
|
||||||
};
|
};
|
||||||
|
UserSchema.statics.setLinkToVerifiedEmail = async function (idapp, username, link_verif_email) {
|
||||||
|
return await User.updateOne({ idapp, username }, { $set: { link_verif_email } });
|
||||||
|
};
|
||||||
|
UserSchema.statics.findByLinkVerifEmail = async function (idapp, link_verif_email) {
|
||||||
|
return await User.findOne({ idapp, link_verif_email });
|
||||||
|
};
|
||||||
// Rimuovo il Partecipa
|
// Rimuovo il Partecipa
|
||||||
UserSchema.statics.removeAttend = async function (idapp, username, id, tab) {
|
UserSchema.statics.removeAttend = async function (idapp, username, id, tab) {
|
||||||
return await User.updateOne({ idapp, username }, { $pull: { 'profile.attend': { id: { $in: [id] }, tab } } });
|
return await User.updateOne({ idapp, username }, { $pull: { 'profile.attend': { id: { $in: [id] }, tab } } });
|
||||||
@@ -6989,28 +6998,24 @@ UserSchema.statics.getTokenByUsernameAndCircuitName = async function (idapp, use
|
|||||||
return user?.profile?.mycircuits?.[0]?.token || null;
|
return user?.profile?.mycircuits?.[0]?.token || null;
|
||||||
};
|
};
|
||||||
|
|
||||||
UserSchema.statics.softDelete = async function(id) {
|
UserSchema.statics.softDelete = async function (id) {
|
||||||
return this.findByIdAndUpdate(
|
return this.findByIdAndUpdate(
|
||||||
id,
|
id,
|
||||||
{
|
{
|
||||||
deleted: true,
|
deleted: true,
|
||||||
deletedAt: new Date()
|
deletedAt: new Date(),
|
||||||
},
|
},
|
||||||
{ new: true }
|
{ new: true }
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
UserSchema.statics.getUsersList = function(idapp) {
|
UserSchema.statics.getUsersList = function (idapp) {
|
||||||
return this.find({
|
return this.find({
|
||||||
idapp: idapp,
|
idapp: idapp,
|
||||||
$or: [
|
$or: [{ deleted: { $exists: false } }, { deleted: false }],
|
||||||
{ deleted: { $exists: false } },
|
|
||||||
{ deleted: false }
|
|
||||||
]
|
|
||||||
}).lean();
|
}).lean();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const User = mongoose.model('User', UserSchema);
|
const User = mongoose.model('User', UserSchema);
|
||||||
|
|
||||||
class Hero {
|
class Hero {
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ module.exports = {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log('error insertIntoDb', e);
|
console.log('error insertIntoDb', e);
|
||||||
}
|
}
|
||||||
|
|||||||
913
src/router/api2_router.js
Normal file
913
src/router/api2_router.js
Normal file
@@ -0,0 +1,913 @@
|
|||||||
|
/**
|
||||||
|
* API2 Router - Ollama Integration
|
||||||
|
*/
|
||||||
|
|
||||||
|
const express = require('express');
|
||||||
|
|
||||||
|
const router = express.Router();
|
||||||
|
|
||||||
|
// Configurazione Ollama
|
||||||
|
const OLLAMA_URL = process.env.OLLAMA_URL || 'http://localhost:11434';
|
||||||
|
const DEFAULT_MODEL = process.env.OLLAMA_DEFAULT_MODEL || 'llama3.2';
|
||||||
|
|
||||||
|
// ============================================
|
||||||
|
// ROUTES PRINCIPALI
|
||||||
|
// ============================================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Health check Ollama
|
||||||
|
* GET /api2/health
|
||||||
|
*/
|
||||||
|
router.get('/health', async (req, res) => {
|
||||||
|
try {
|
||||||
|
const response = await fetch(`${OLLAMA_URL}/api/tags`);
|
||||||
|
if (response.ok) {
|
||||||
|
const data = await response.json();
|
||||||
|
res.json({
|
||||||
|
status: 'ok',
|
||||||
|
ollama: 'connected',
|
||||||
|
modelsCount: data.models?.length || 0
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
res.status(503).json({ status: 'error', ollama: 'disconnected' });
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
res.status(503).json({
|
||||||
|
status: 'error',
|
||||||
|
ollama: 'unreachable',
|
||||||
|
message: error.message
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lista modelli disponibili
|
||||||
|
* GET /api2/models
|
||||||
|
*/
|
||||||
|
router.get('/models', async (req, res) => {
|
||||||
|
try {
|
||||||
|
|
||||||
|
const response = await fetch(`${OLLAMA_URL}/api/tags`);
|
||||||
|
if (!response.ok) {
|
||||||
|
console.error('[api2/models] Error:', response.status);
|
||||||
|
throw new Error(`Ollama error: ${response.status}`);
|
||||||
|
}
|
||||||
|
const data = await response.json();
|
||||||
|
res.json({ models: data.models || [] });
|
||||||
|
} catch (error) {
|
||||||
|
console.error('[api2/models] Error:', error);
|
||||||
|
res.status(500).json({ error: error.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Info modello specifico
|
||||||
|
* POST /api2/models/info
|
||||||
|
*/
|
||||||
|
router.post('/models/info', async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { model } = req.body;
|
||||||
|
if (!model) {
|
||||||
|
return res.status(400).json({ error: 'Model name richiesto' });
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await fetch(`${OLLAMA_URL}/api/show`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({ name: model }),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`Ollama error: ${response.status}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
res.json(data);
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).json({ error: error.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// ============================================
|
||||||
|
// GENERAZIONE TESTO
|
||||||
|
// ============================================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generazione testo (non-streaming)
|
||||||
|
* POST /api2/generate
|
||||||
|
*/
|
||||||
|
router.post('/generate', async (req, res) => {
|
||||||
|
try {
|
||||||
|
const {
|
||||||
|
model = DEFAULT_MODEL,
|
||||||
|
prompt,
|
||||||
|
temperature = 0.7,
|
||||||
|
maxTokens,
|
||||||
|
system,
|
||||||
|
topP,
|
||||||
|
topK,
|
||||||
|
} = req.body;
|
||||||
|
|
||||||
|
if (!prompt) {
|
||||||
|
return res.status(400).json({ error: 'Prompt richiesto' });
|
||||||
|
}
|
||||||
|
|
||||||
|
const payload = {
|
||||||
|
model,
|
||||||
|
prompt,
|
||||||
|
stream: false,
|
||||||
|
options: {
|
||||||
|
temperature,
|
||||||
|
...(maxTokens && { num_predict: maxTokens }),
|
||||||
|
...(topP && { top_p: topP }),
|
||||||
|
...(topK && { top_k: topK }),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
if (system) payload.system = system;
|
||||||
|
|
||||||
|
const response = await fetch(`${OLLAMA_URL}/api/generate`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify(payload),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`Ollama error: ${response.status}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
res.json({
|
||||||
|
response: data.response,
|
||||||
|
model: data.model,
|
||||||
|
totalDuration: data.total_duration,
|
||||||
|
loadDuration: data.load_duration,
|
||||||
|
promptEvalCount: data.prompt_eval_count,
|
||||||
|
evalCount: data.eval_count,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('[api2/generate] Error:', error);
|
||||||
|
res.status(500).json({ error: error.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generazione testo con streaming (SSE)
|
||||||
|
* POST /api2/generate/stream
|
||||||
|
*/
|
||||||
|
router.post('/generate/stream', async (req, res) => {
|
||||||
|
try {
|
||||||
|
const {
|
||||||
|
model = DEFAULT_MODEL,
|
||||||
|
prompt,
|
||||||
|
temperature = 0.7,
|
||||||
|
system,
|
||||||
|
maxTokens,
|
||||||
|
} = req.body;
|
||||||
|
|
||||||
|
if (!prompt) {
|
||||||
|
return res.status(400).json({ error: 'Prompt richiesto' });
|
||||||
|
}
|
||||||
|
|
||||||
|
const payload = {
|
||||||
|
model,
|
||||||
|
prompt,
|
||||||
|
stream: true,
|
||||||
|
options: {
|
||||||
|
temperature,
|
||||||
|
...(maxTokens && { num_predict: maxTokens }),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
if (system) payload.system = system;
|
||||||
|
|
||||||
|
const response = await fetch(`${OLLAMA_URL}/api/generate`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify(payload),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`Ollama error: ${response.status}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup SSE
|
||||||
|
res.setHeader('Content-Type', 'text/event-stream');
|
||||||
|
res.setHeader('Cache-Control', 'no-cache');
|
||||||
|
res.setHeader('Connection', 'keep-alive');
|
||||||
|
res.setHeader('X-Accel-Buffering', 'no');
|
||||||
|
|
||||||
|
const reader = response.body.getReader();
|
||||||
|
const decoder = new TextDecoder();
|
||||||
|
|
||||||
|
const pump = async () => {
|
||||||
|
try {
|
||||||
|
while (true) {
|
||||||
|
const { done, value } = await reader.read();
|
||||||
|
if (done) {
|
||||||
|
res.write('data: [DONE]\n\n');
|
||||||
|
res.end();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const chunk = decoder.decode(value);
|
||||||
|
const lines = chunk.split('\n').filter(line => line.trim());
|
||||||
|
|
||||||
|
for (const line of lines) {
|
||||||
|
try {
|
||||||
|
const json = JSON.parse(line);
|
||||||
|
res.write(`data: ${JSON.stringify(json)}\n\n`);
|
||||||
|
} catch (e) {
|
||||||
|
// Ignora linee non JSON
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('[api2/generate/stream] Stream error:', error);
|
||||||
|
res.end();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Handle client disconnect
|
||||||
|
req.on('close', () => {
|
||||||
|
reader.cancel();
|
||||||
|
});
|
||||||
|
|
||||||
|
pump();
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('[api2/generate/stream] Error:', error);
|
||||||
|
res.status(500).json({ error: error.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// ============================================
|
||||||
|
// CHAT
|
||||||
|
// ============================================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Chat (non-streaming)
|
||||||
|
* POST /api2/chat
|
||||||
|
*/
|
||||||
|
router.post('/chat', async (req, res) => {
|
||||||
|
try {
|
||||||
|
const {
|
||||||
|
model = DEFAULT_MODEL,
|
||||||
|
messages,
|
||||||
|
temperature = 0.7,
|
||||||
|
system,
|
||||||
|
maxTokens,
|
||||||
|
} = req.body;
|
||||||
|
|
||||||
|
if (!messages || !Array.isArray(messages)) {
|
||||||
|
return res.status(400).json({ error: 'Messages array richiesto' });
|
||||||
|
}
|
||||||
|
|
||||||
|
const payload = {
|
||||||
|
model,
|
||||||
|
messages,
|
||||||
|
stream: false,
|
||||||
|
options: {
|
||||||
|
temperature,
|
||||||
|
...(maxTokens && { num_predict: maxTokens }),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
if (system) payload.system = system;
|
||||||
|
|
||||||
|
// console.log('payload', payload);
|
||||||
|
|
||||||
|
const response = await fetch(`${OLLAMA_URL}/api/chat`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify(payload),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`Ollama error: ${response.status} - ${response.statusText}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
res.json({
|
||||||
|
message: data.message,
|
||||||
|
model: data.model,
|
||||||
|
totalDuration: data.total_duration,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('[api2/chat] Error:', error);
|
||||||
|
res.status(500).json({ error: error.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Chat con streaming (SSE)
|
||||||
|
* POST /api2/chat/stream
|
||||||
|
*/
|
||||||
|
router.post('/chat/stream', async (req, res) => {
|
||||||
|
try {
|
||||||
|
const {
|
||||||
|
model = DEFAULT_MODEL,
|
||||||
|
messages,
|
||||||
|
temperature = 0.7,
|
||||||
|
system,
|
||||||
|
maxTokens,
|
||||||
|
} = req.body;
|
||||||
|
|
||||||
|
if (!messages || !Array.isArray(messages)) {
|
||||||
|
return res.status(400).json({ error: 'Messages array richiesto' });
|
||||||
|
}
|
||||||
|
|
||||||
|
const payload = {
|
||||||
|
model,
|
||||||
|
messages,
|
||||||
|
stream: true,
|
||||||
|
options: {
|
||||||
|
temperature,
|
||||||
|
...(maxTokens && { num_predict: maxTokens }),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
if (system) payload.system = system;
|
||||||
|
|
||||||
|
const response = await fetch(`${OLLAMA_URL}/api/chat`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify(payload),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`Ollama error: ${response.status}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup SSE
|
||||||
|
res.setHeader('Content-Type', 'text/event-stream');
|
||||||
|
res.setHeader('Cache-Control', 'no-cache');
|
||||||
|
res.setHeader('Connection', 'keep-alive');
|
||||||
|
res.setHeader('X-Accel-Buffering', 'no');
|
||||||
|
|
||||||
|
const reader = response.body.getReader();
|
||||||
|
const decoder = new TextDecoder();
|
||||||
|
|
||||||
|
const pump = async () => {
|
||||||
|
try {
|
||||||
|
while (true) {
|
||||||
|
const { done, value } = await reader.read();
|
||||||
|
if (done) {
|
||||||
|
res.write('data: [DONE]\n\n');
|
||||||
|
res.end();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const chunk = decoder.decode(value);
|
||||||
|
const lines = chunk.split('\n').filter(line => line.trim());
|
||||||
|
|
||||||
|
for (const line of lines) {
|
||||||
|
try {
|
||||||
|
const json = JSON.parse(line);
|
||||||
|
res.write(`data: ${JSON.stringify(json)}\n\n`);
|
||||||
|
} catch (e) {
|
||||||
|
// Ignora linee non JSON
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('[api2/chat/stream] Stream error:', error);
|
||||||
|
res.end();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Handle client disconnect
|
||||||
|
req.on('close', () => {
|
||||||
|
reader.cancel();
|
||||||
|
});
|
||||||
|
|
||||||
|
pump();
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('[api2/chat/stream] Error:', error);
|
||||||
|
res.status(500).json({ error: error.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// ============================================
|
||||||
|
// ENDPOINTS HELPER
|
||||||
|
// ============================================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Genera codice
|
||||||
|
* POST /api2/code
|
||||||
|
*/
|
||||||
|
router.post('/code', async (req, res) => {
|
||||||
|
try {
|
||||||
|
const {
|
||||||
|
prompt,
|
||||||
|
language = 'javascript',
|
||||||
|
model = DEFAULT_MODEL,
|
||||||
|
temperature = 0.3,
|
||||||
|
} = req.body;
|
||||||
|
|
||||||
|
if (!prompt) {
|
||||||
|
return res.status(400).json({ error: 'Prompt richiesto' });
|
||||||
|
}
|
||||||
|
|
||||||
|
const systemPrompt = `Sei un esperto programmatore. Rispondi SOLO con codice ${language} valido e funzionante, senza spiegazioni prima o dopo. Usa commenti nel codice se necessario per spiegare.`;
|
||||||
|
|
||||||
|
const response = await fetch(`${OLLAMA_URL}/api/generate`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({
|
||||||
|
model,
|
||||||
|
prompt: `Scrivi codice ${language} per: ${prompt}`,
|
||||||
|
system: systemPrompt,
|
||||||
|
stream: false,
|
||||||
|
options: { temperature },
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`Ollama error: ${response.status}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
res.json({
|
||||||
|
code: data.response,
|
||||||
|
language,
|
||||||
|
model: data.model,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('[api2/code] Error:', error);
|
||||||
|
res.status(500).json({ error: error.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Traduci testo
|
||||||
|
* POST /api/translate
|
||||||
|
*/
|
||||||
|
router.post('/translate', async (req, res) => {
|
||||||
|
try {
|
||||||
|
const {
|
||||||
|
text,
|
||||||
|
targetLang = 'english',
|
||||||
|
sourceLang,
|
||||||
|
model = DEFAULT_MODEL,
|
||||||
|
} = req.body;
|
||||||
|
|
||||||
|
if (!text) {
|
||||||
|
return res.status(400).json({ error: 'Text richiesto' });
|
||||||
|
}
|
||||||
|
|
||||||
|
const sourceInfo = sourceLang ? ` da ${sourceLang}` : '';
|
||||||
|
const prompt = `Traduci il seguente testo${sourceInfo} in ${targetLang}. Rispondi SOLO con la traduzione, senza spiegazioni:\n\n${text}`;
|
||||||
|
|
||||||
|
const response = await fetch(`${OLLAMA_URL}/api/generate`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({
|
||||||
|
model,
|
||||||
|
prompt,
|
||||||
|
stream: false,
|
||||||
|
options: { temperature: 0.3 },
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`Ollama error: ${response.status}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
res.json({
|
||||||
|
translation: data.response.trim(),
|
||||||
|
targetLang,
|
||||||
|
sourceLang,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('[api2/translate] Error:', error);
|
||||||
|
res.status(500).json({ error: error.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Riassumi testo
|
||||||
|
* POST /api/summarize
|
||||||
|
*/
|
||||||
|
router.post('/summarize', async (req, res) => {
|
||||||
|
try {
|
||||||
|
const {
|
||||||
|
text,
|
||||||
|
maxLength,
|
||||||
|
style = 'conciso', // conciso, dettagliato, bullet
|
||||||
|
model = DEFAULT_MODEL,
|
||||||
|
} = req.body;
|
||||||
|
|
||||||
|
if (!text) {
|
||||||
|
return res.status(400).json({ error: 'Text richiesto' });
|
||||||
|
}
|
||||||
|
|
||||||
|
let styleInstruction = '';
|
||||||
|
switch (style) {
|
||||||
|
case 'bullet':
|
||||||
|
styleInstruction = 'Usa un elenco puntato.';
|
||||||
|
break;
|
||||||
|
case 'dettagliato':
|
||||||
|
styleInstruction = 'Fornisci un riassunto dettagliato.';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
styleInstruction = 'Sii conciso e chiaro.';
|
||||||
|
}
|
||||||
|
|
||||||
|
const lengthInstruction = maxLength ? ` Massimo ${maxLength} parole.` : '';
|
||||||
|
|
||||||
|
const response = await fetch(`${OLLAMA_URL}/api/generate`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({
|
||||||
|
model,
|
||||||
|
prompt: `Riassumi il seguente testo. ${styleInstruction}${lengthInstruction}\n\n${text}`,
|
||||||
|
stream: false,
|
||||||
|
options: { temperature: 0.5 },
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`Ollama error: ${response.status}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
res.json({
|
||||||
|
summary: data.response.trim(),
|
||||||
|
style,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('[api2/summarize] Error:', error);
|
||||||
|
res.status(500).json({ error: error.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Analisi sentiment
|
||||||
|
* POST /api/sentiment
|
||||||
|
*/
|
||||||
|
router.post('/sentiment', async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { text, model = DEFAULT_MODEL } = req.body;
|
||||||
|
|
||||||
|
if (!text) {
|
||||||
|
return res.status(400).json({ error: 'Text richiesto' });
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await fetch(`${OLLAMA_URL}/api/generate`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({
|
||||||
|
model,
|
||||||
|
prompt: `Analizza il sentiment del seguente testo e rispondi SOLO con un JSON valido nel formato:
|
||||||
|
{"sentiment": "positive" | "negative" | "neutral" | "mixed", "confidence": 0.0-1.0, "emotions": ["emotion1", "emotion2"], "explanation": "breve spiegazione"}
|
||||||
|
|
||||||
|
Testo da analizzare:
|
||||||
|
${text}`,
|
||||||
|
stream: false,
|
||||||
|
options: { temperature: 0.1 },
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`Ollama error: ${response.status}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
|
||||||
|
try {
|
||||||
|
const jsonMatch = data.response.match(/\{[\s\S]*\}/);
|
||||||
|
if (jsonMatch) {
|
||||||
|
const parsed = JSON.parse(jsonMatch[0]);
|
||||||
|
res.json(parsed);
|
||||||
|
} else {
|
||||||
|
res.json({ sentiment: 'unknown', raw: data.response });
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
res.json({ sentiment: 'unknown', raw: data.response });
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('[api2/sentiment] Error:', error);
|
||||||
|
res.status(500).json({ error: error.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Estrai JSON strutturato da testo
|
||||||
|
* POST /api/extract
|
||||||
|
*/
|
||||||
|
router.post('/extract', async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { text, schema, model = DEFAULT_MODEL } = req.body;
|
||||||
|
|
||||||
|
if (!text) {
|
||||||
|
return res.status(400).json({ error: 'Text richiesto' });
|
||||||
|
}
|
||||||
|
if (!schema) {
|
||||||
|
return res.status(400).json({ error: 'Schema richiesto' });
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await fetch(`${OLLAMA_URL}/api/generate`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({
|
||||||
|
model,
|
||||||
|
prompt: `Estrai le informazioni dal seguente testo e restituisci SOLO un JSON valido con questa struttura:
|
||||||
|
${JSON.stringify(schema, null, 2)}
|
||||||
|
|
||||||
|
Testo da analizzare:
|
||||||
|
${text}
|
||||||
|
|
||||||
|
Rispondi SOLO con il JSON, senza altro testo.`,
|
||||||
|
stream: false,
|
||||||
|
options: { temperature: 0.1 },
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`Ollama error: ${response.status}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
|
||||||
|
try {
|
||||||
|
const jsonMatch = data.response.match(/\{[\s\S]*\}/);
|
||||||
|
if (jsonMatch) {
|
||||||
|
res.json(JSON.parse(jsonMatch[0]));
|
||||||
|
} else {
|
||||||
|
res.status(422).json({ error: 'Could not parse JSON', raw: data.response });
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
res.status(422).json({ error: 'Invalid JSON response', raw: data.response });
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('[api2/extract] Error:', error);
|
||||||
|
res.status(500).json({ error: error.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Correggi grammatica
|
||||||
|
* POST /api/grammar
|
||||||
|
*/
|
||||||
|
router.post('/grammar', async (req, res) => {
|
||||||
|
try {
|
||||||
|
const {
|
||||||
|
text,
|
||||||
|
language = 'italiano',
|
||||||
|
model = DEFAULT_MODEL,
|
||||||
|
} = req.body;
|
||||||
|
|
||||||
|
if (!text) {
|
||||||
|
return res.status(400).json({ error: 'Text richiesto' });
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await fetch(`${OLLAMA_URL}/api/generate`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({
|
||||||
|
model,
|
||||||
|
prompt: `Correggi gli errori grammaticali e di ortografia nel seguente testo in ${language}. Rispondi SOLO con il testo corretto, senza spiegazioni:\n\n${text}`,
|
||||||
|
stream: false,
|
||||||
|
options: { temperature: 0.2 },
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`Ollama error: ${response.status}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
res.json({
|
||||||
|
corrected: data.response.trim(),
|
||||||
|
original: text,
|
||||||
|
language,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('[api2/grammar] Error:', error);
|
||||||
|
res.status(500).json({ error: error.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rispondi a domanda con contesto
|
||||||
|
* POST /api/qa
|
||||||
|
*/
|
||||||
|
router.post('/qa', async (req, res) => {
|
||||||
|
try {
|
||||||
|
const {
|
||||||
|
question,
|
||||||
|
context,
|
||||||
|
model = DEFAULT_MODEL,
|
||||||
|
} = req.body;
|
||||||
|
|
||||||
|
if (!question) {
|
||||||
|
return res.status(400).json({ error: 'Question richiesta' });
|
||||||
|
}
|
||||||
|
if (!context) {
|
||||||
|
return res.status(400).json({ error: 'Context richiesto' });
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await fetch(`${OLLAMA_URL}/api/generate`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({
|
||||||
|
model,
|
||||||
|
prompt: `Basandoti SOLO sul seguente contesto, rispondi alla domanda. Se la risposta non è nel contesto, dì che non hai abbastanza informazioni.
|
||||||
|
|
||||||
|
Contesto:
|
||||||
|
${context}
|
||||||
|
|
||||||
|
Domanda: ${question}
|
||||||
|
|
||||||
|
Risposta:`,
|
||||||
|
stream: false,
|
||||||
|
options: { temperature: 0.3 },
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`Ollama error: ${response.status}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
res.json({
|
||||||
|
answer: data.response.trim(),
|
||||||
|
question,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('[api2/qa] Error:', error);
|
||||||
|
res.status(500).json({ error: error.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Genera embeddings
|
||||||
|
* POST /api/embeddings
|
||||||
|
*/
|
||||||
|
router.post('/embeddings', async (req, res) => {
|
||||||
|
try {
|
||||||
|
const {
|
||||||
|
text,
|
||||||
|
model = 'nomic-embed-text',
|
||||||
|
} = req.body;
|
||||||
|
|
||||||
|
if (!text) {
|
||||||
|
return res.status(400).json({ error: 'Text richiesto' });
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await fetch(`${OLLAMA_URL}/api/embeddings`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({
|
||||||
|
model,
|
||||||
|
prompt: text,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`Ollama error: ${response.status}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
res.json({
|
||||||
|
embedding: data.embedding,
|
||||||
|
dimensions: data.embedding?.length,
|
||||||
|
model,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('[api2/embeddings] Error:', error);
|
||||||
|
res.status(500).json({ error: error.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Classifica testo in categorie
|
||||||
|
* POST /api/classify
|
||||||
|
*/
|
||||||
|
router.post('/classify', async (req, res) => {
|
||||||
|
try {
|
||||||
|
const {
|
||||||
|
text,
|
||||||
|
categories,
|
||||||
|
model = DEFAULT_MODEL,
|
||||||
|
} = req.body;
|
||||||
|
|
||||||
|
if (!text) {
|
||||||
|
return res.status(400).json({ error: 'Text richiesto' });
|
||||||
|
}
|
||||||
|
if (!categories || !Array.isArray(categories)) {
|
||||||
|
return res.status(400).json({ error: 'Categories array richiesto' });
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await fetch(`${OLLAMA_URL}/api/generate`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({
|
||||||
|
model,
|
||||||
|
prompt: `Classifica il seguente testo in UNA delle seguenti categorie: ${categories.join(', ')}
|
||||||
|
|
||||||
|
Rispondi SOLO con un JSON nel formato:
|
||||||
|
{"category": "categoria_scelta", "confidence": 0.0-1.0, "reason": "breve motivazione"}
|
||||||
|
|
||||||
|
Testo: ${text}`,
|
||||||
|
stream: false,
|
||||||
|
options: { temperature: 0.1 },
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`Ollama error: ${response.status}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
|
||||||
|
try {
|
||||||
|
const jsonMatch = data.response.match(/\{[\s\S]*\}/);
|
||||||
|
if (jsonMatch) {
|
||||||
|
res.json(JSON.parse(jsonMatch[0]));
|
||||||
|
} else {
|
||||||
|
res.json({ category: 'unknown', raw: data.response });
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
res.json({ category: 'unknown', raw: data.response });
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('[api2/classify] Error:', error);
|
||||||
|
res.status(500).json({ error: error.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pull/scarica un nuovo modello
|
||||||
|
* POST /api2/models/pull
|
||||||
|
*/
|
||||||
|
router.post('/models/pull', async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { model } = req.body;
|
||||||
|
if (!model) {
|
||||||
|
return res.status(400).json({ error: 'Model name richiesto' });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Streaming del progresso
|
||||||
|
res.setHeader('Content-Type', 'text/event-stream');
|
||||||
|
res.setHeader('Cache-Control', 'no-cache');
|
||||||
|
res.setHeader('Connection', 'keep-alive');
|
||||||
|
|
||||||
|
const response = await fetch(`${OLLAMA_URL}/api/pull`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({ name: model, stream: true }),
|
||||||
|
});
|
||||||
|
|
||||||
|
const reader = response.body.getReader();
|
||||||
|
const decoder = new TextDecoder();
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
const { done, value } = await reader.read();
|
||||||
|
if (done) {
|
||||||
|
res.write('data: [DONE]\n\n');
|
||||||
|
res.end();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const chunk = decoder.decode(value);
|
||||||
|
res.write(`data: ${chunk}\n\n`);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).json({ error: error.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Elimina un modello
|
||||||
|
* DELETE /api2/models/:name
|
||||||
|
*/
|
||||||
|
router.delete('/models/:name', async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { name } = req.params;
|
||||||
|
|
||||||
|
const response = await fetch(`${OLLAMA_URL}/api/delete`, {
|
||||||
|
method: 'DELETE',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({ name }),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
res.json({ success: true, message: `Modello ${name} eliminato` });
|
||||||
|
} else {
|
||||||
|
throw new Error(`Errore eliminazione: ${response.status}`);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).json({ error: error.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// ============================================
|
||||||
|
// EXPORT
|
||||||
|
// ============================================
|
||||||
|
|
||||||
|
module.exports = router;
|
||||||
@@ -300,6 +300,44 @@ router.post(process.env.LINKVERIF_REG, (req, res) => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
router.post(process.env.CHECKREVERIF_EMAIL, (req, res) => {
|
||||||
|
const body = _.pick(req.body, ['idapp', 'idlink']);
|
||||||
|
const idapp = body.idapp;
|
||||||
|
const idlink = body.idlink;
|
||||||
|
|
||||||
|
// Cerco l'idlink se è ancora da Verificare
|
||||||
|
|
||||||
|
User.findByLinkVerifEmail(idapp, idlink)
|
||||||
|
.then((user) => {
|
||||||
|
if (!user) {
|
||||||
|
//console.log("NON TROVATO!");
|
||||||
|
return res.status(404).send({code: RIS_CODE_ERRORE, msg: 'Verifica email non andata a buon fine. Ripetere.'});
|
||||||
|
} else {
|
||||||
|
console.log('user', user);
|
||||||
|
if (user.verified_email) {
|
||||||
|
res.send({
|
||||||
|
code: server_constants.RIS_CODE_EMAIL_ALREADY_VERIFIED,
|
||||||
|
msg: tools.getres__("L'Email è già stata Verificata", res),
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
user.verified_email = true;
|
||||||
|
user.lasttimeonline = new Date();
|
||||||
|
user.save().then(() => {
|
||||||
|
//console.log("TROVATOOOOOO!");
|
||||||
|
res.send({
|
||||||
|
code: server_constants.RIS_CODE_EMAIL_VERIFIED,
|
||||||
|
msg: tools.getres__('EMAIL', res) + ' ' + tools.getres__('VERIF', res),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
console.log(process.env.LINKVERIF_REG, e.message);
|
||||||
|
res.status(400).send();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
router.post(process.env.ADD_NEW_SITE, async (req, res) => {
|
router.post(process.env.ADD_NEW_SITE, async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const body = req.body;
|
const body = req.body;
|
||||||
|
|||||||
@@ -506,13 +506,15 @@ router.post('/profile', authenticate, (req, res) => {
|
|||||||
const perm = req.user ? req.user.perm : tools.Perm.PERM_NONE;
|
const perm = req.user ? req.user.perm : tools.Perm.PERM_NONE;
|
||||||
const username = req.body['username'];
|
const username = req.body['username'];
|
||||||
const idapp = req.body.idapp;
|
const idapp = req.body.idapp;
|
||||||
|
const idnotif = req.body['idnotif'] || '';
|
||||||
|
|
||||||
//++Todo: controlla che tipo di dati ha il permesso di leggere
|
//++Todo: controlla che tipo di dati ha il permesso di leggere
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Check if ìs a Notif to read
|
// Check if ìs a Notif to read
|
||||||
const idnotif = req.body['idnotif'] ? req.body['idnotif'] : '';
|
if (idnotif) {
|
||||||
SendNotif.setNotifAsRead(idapp, usernameOrig, idnotif);
|
SendNotif.setNotifAsRead(idapp, usernameOrig, idnotif);
|
||||||
|
}
|
||||||
|
|
||||||
return User.getUserProfileByUsername(idapp, username, usernameOrig, false, perm)
|
return User.getUserProfileByUsername(idapp, username, usernameOrig, false, perm)
|
||||||
.then((ris) => {
|
.then((ris) => {
|
||||||
@@ -601,6 +603,7 @@ router.post('/panel', authenticate, async (req, res) => {
|
|||||||
username: 1,
|
username: 1,
|
||||||
name: 1,
|
name: 1,
|
||||||
surname: 1,
|
surname: 1,
|
||||||
|
verified_email: 1,
|
||||||
email: 1,
|
email: 1,
|
||||||
verified_by_aportador: 1,
|
verified_by_aportador: 1,
|
||||||
aportador_solidario: 1,
|
aportador_solidario: 1,
|
||||||
@@ -1124,6 +1127,11 @@ async function eseguiDbOpUser(idapp, mydata, locale, req, res) {
|
|||||||
await User.findOneAndUpdate({ _id: mydata._id }, { $set: { 'profile.noCircuit': mydata.value } });
|
await User.findOneAndUpdate({ _id: mydata._id }, { $set: { 'profile.noCircuit': mydata.value } });
|
||||||
} else if (mydata.dbop === 'noComune') {
|
} else if (mydata.dbop === 'noComune') {
|
||||||
await User.findOneAndUpdate({ _id: mydata._id }, { $set: { 'profile.noComune': mydata.value } });
|
await User.findOneAndUpdate({ _id: mydata._id }, { $set: { 'profile.noComune': mydata.value } });
|
||||||
|
} else if (mydata.dbop === 'verifiedemail') {
|
||||||
|
await User.findOneAndUpdate({ _id: mydata._id }, { $set: { 'verified_email': mydata.value } });
|
||||||
|
} else if (mydata.dbop === 'resendVerificationEmail') {
|
||||||
|
// Invia la email di Verifica email
|
||||||
|
const ris = await sendemail.sendEmail_ReVerifyingEmail(mydata, idapp);
|
||||||
} else if (mydata.dbop === 'noCircIta') {
|
} else if (mydata.dbop === 'noCircIta') {
|
||||||
await User.findOneAndUpdate({ _id: mydata._id }, { $set: { 'profile.noCircIta': mydata.value } });
|
await User.findOneAndUpdate({ _id: mydata._id }, { $set: { 'profile.noCircIta': mydata.value } });
|
||||||
} else if (mydata.dbop === 'insert_circuito_ita') {
|
} else if (mydata.dbop === 'insert_circuito_ita') {
|
||||||
|
|||||||
@@ -494,6 +494,21 @@ module.exports = {
|
|||||||
const strlinkreg = tools.getHostByIdApp(idapp) + process.env.LINKVERIF_REG + `/?idapp=${idapp}&idlink=${idreg}`;
|
const strlinkreg = tools.getHostByIdApp(idapp) + process.env.LINKVERIF_REG + `/?idapp=${idapp}&idlink=${idreg}`;
|
||||||
return strlinkreg;
|
return strlinkreg;
|
||||||
},
|
},
|
||||||
|
getlinkVerifyEmail: async function (idapp, email, username) {
|
||||||
|
try {
|
||||||
|
const reg = require('./reg/registration');
|
||||||
|
|
||||||
|
|
||||||
|
const idverif = reg.getlinkregByEmail(idapp, email, username);
|
||||||
|
|
||||||
|
await User.setLinkToVerifiedEmail(idapp, username, idverif);
|
||||||
|
|
||||||
|
const strlinkreg = tools.getHostByIdApp(idapp) + process.env.CHECKREVERIF_EMAIL + `/?idapp=${idapp}&idlink=${idverif}`;
|
||||||
|
return strlinkreg;
|
||||||
|
} catch (e) {
|
||||||
|
console.error('ERROR getlinkVerifyEmail');
|
||||||
|
}
|
||||||
|
},
|
||||||
getlinkInvitoReg: function (idapp, dati) {
|
getlinkInvitoReg: function (idapp, dati) {
|
||||||
const strlinkreg = tools.getHostByIdApp(idapp) + `/invitetoreg/${dati.token}`;
|
const strlinkreg = tools.getHostByIdApp(idapp) + `/invitetoreg/${dati.token}`;
|
||||||
return strlinkreg;
|
return strlinkreg;
|
||||||
@@ -675,6 +690,38 @@ module.exports = {
|
|||||||
console.error('Err sendEmail_Utente_Ammesso', e);
|
console.error('Err sendEmail_Utente_Ammesso', e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
sendEmail_ReVerifyingEmail: async function (dati, idapp) {
|
||||||
|
try {
|
||||||
|
const user = await User.getUserById(idapp, dati._id);
|
||||||
|
const lang = user.lang;
|
||||||
|
const username = user.username;
|
||||||
|
const email = user.email;
|
||||||
|
|
||||||
|
let mylocalsconf = {
|
||||||
|
idapp,
|
||||||
|
dataemail: await this.getdataemail(idapp),
|
||||||
|
baseurl: tools.getHostByIdApp(idapp),
|
||||||
|
locale: lang,
|
||||||
|
nomeapp: tools.getNomeAppByIdApp(idapp),
|
||||||
|
strlinksito: tools.getHostByIdApp(idapp),
|
||||||
|
//strlinkreg: this.getlinkReg(idapp, idreg),
|
||||||
|
emailto: email,
|
||||||
|
name: user.name,
|
||||||
|
username: user.username,
|
||||||
|
verifyLink: await this.getlinkVerifyEmail(idapp, email, username),
|
||||||
|
user,
|
||||||
|
supportEmail: tools.getContactEmailSupportBydApp(idapp),
|
||||||
|
};
|
||||||
|
|
||||||
|
const quale_email_inviare = this.getPathEmail(idapp, 'reg_resend_email_to_verifiyng') + '/' + lang;
|
||||||
|
|
||||||
|
const ris = await this.sendEmail_base(quale_email_inviare, email, mylocalsconf, '');
|
||||||
|
|
||||||
|
return ris;
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Err sendEmail_ReVerifyingEmail', e);
|
||||||
|
}
|
||||||
|
},
|
||||||
sendEmail_Utente_Abilitato_Circuito_FidoConcesso: async function (lang, emailto, user, idapp, dati) {
|
sendEmail_Utente_Abilitato_Circuito_FidoConcesso: async function (lang, emailto, user, idapp, dati) {
|
||||||
try {
|
try {
|
||||||
let mylocalsconf = {
|
let mylocalsconf = {
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ function setupRouters(app) {
|
|||||||
['/aitools', 'aitools_router'],
|
['/aitools', 'aitools_router'],
|
||||||
['/apisqlsrv', 'articleRoutes'],
|
['/apisqlsrv', 'articleRoutes'],
|
||||||
['/api', 'api_router'],
|
['/api', 'api_router'],
|
||||||
|
['/api2', 'api2_router'],
|
||||||
['/api/telegram', 'telegram_router'],
|
['/api/telegram', 'telegram_router'],
|
||||||
['/inviti', 'invitaAmicoRoutes'],
|
['/inviti', 'invitaAmicoRoutes'],
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -146,6 +146,7 @@ connectToDatabase(connectionUrl, options)
|
|||||||
const aitools_router = require('./router/aitools_router');
|
const aitools_router = require('./router/aitools_router');
|
||||||
const article_router = require('./router/articleRoutes');
|
const article_router = require('./router/articleRoutes');
|
||||||
const api_router = require('./router/api_router');
|
const api_router = require('./router/api_router');
|
||||||
|
const api2_router = require('./router/api2_router');
|
||||||
|
|
||||||
const { MyEvent } = require('./models/myevent');
|
const { MyEvent } = require('./models/myevent');
|
||||||
|
|
||||||
@@ -252,6 +253,7 @@ connectToDatabase(connectionUrl, options)
|
|||||||
app.use('/aitools', aitools_router);
|
app.use('/aitools', aitools_router);
|
||||||
app.use('/apisqlsrv', article_router);
|
app.use('/apisqlsrv', article_router);
|
||||||
app.use('/api', api_router);
|
app.use('/api', api_router);
|
||||||
|
app.use('/api2', api2_router);
|
||||||
|
|
||||||
mystart();
|
mystart();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -2023,6 +2023,19 @@ module.exports = {
|
|||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getContactEmailSupportBydApp: function (idapp, option) {
|
||||||
|
const myapp = this.MYAPPS.find((item) => item.idapp === idapp);
|
||||||
|
if (myapp) {
|
||||||
|
if (myapp.hasOwnProperty('contacts')) {
|
||||||
|
if (myapp.confsite.hasOwnProperty('email')) {
|
||||||
|
return myapp.contacts.email;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return '';
|
||||||
|
},
|
||||||
|
|
||||||
getEnableTokenExpiredByIdApp: function (idapp) {
|
getEnableTokenExpiredByIdApp: function (idapp) {
|
||||||
const myapp = this.MYAPPS.find((item) => item.idapp === idapp);
|
const myapp = this.MYAPPS.find((item) => item.idapp === idapp);
|
||||||
if (myapp && myapp.confpages && myapp.confpages.hasOwnProperty('enableTokenExpired')) {
|
if (myapp && myapp.confpages && myapp.confpages.hasOwnProperty('enableTokenExpired')) {
|
||||||
@@ -5849,6 +5862,10 @@ module.exports = {
|
|||||||
let mystr = '';
|
let mystr = '';
|
||||||
let userfrom = '';
|
let userfrom = '';
|
||||||
let userto = '';
|
let userto = '';
|
||||||
|
let namefrom = '';
|
||||||
|
let surnamefrom = '';
|
||||||
|
let nameto = '';
|
||||||
|
let surnameto = '';
|
||||||
|
|
||||||
let profilefrom = null;
|
let profilefrom = null;
|
||||||
let profileto = null;
|
let profileto = null;
|
||||||
@@ -5866,6 +5883,8 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
if (mov.userfrom) {
|
if (mov.userfrom) {
|
||||||
userfrom += mov.userfrom.username;
|
userfrom += mov.userfrom.username;
|
||||||
|
namefrom = mov.userfrom.name;
|
||||||
|
surnamefrom = mov.userfrom.surname;
|
||||||
profilefrom = mov.userfrom.profile;
|
profilefrom = mov.userfrom.profile;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5879,14 +5898,16 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
if (mov.userto) {
|
if (mov.userto) {
|
||||||
userto += mov.userto.username;
|
userto += mov.userto.username;
|
||||||
|
nameto = mov.userto.name;
|
||||||
|
surnameto = mov.userto.surname;
|
||||||
profileto = mov.userto.profile;
|
profileto = mov.userto.profile;
|
||||||
}
|
}
|
||||||
|
|
||||||
// mystr = t('movement.from') + userfrom + ' ' + t('movement.to') + userto
|
// mystr = t('movement.from') + userfrom + ' ' + t('movement.to') + userto
|
||||||
|
|
||||||
return {
|
return {
|
||||||
userfrom: { profile: profilefrom, username: userfrom },
|
userfrom: { profile: profilefrom, username: userfrom, name: namefrom, surname: surnamefrom },
|
||||||
userto: { profile: profileto, username: userto },
|
userto: { profile: profileto, username: userto, name: nameto, surname: surnameto },
|
||||||
tipocontofrom,
|
tipocontofrom,
|
||||||
tipocontoto,
|
tipocontoto,
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user