- aggiornata la grafica della Home di RISO

- Profilo Completition
- Email Verificata
- Invita un Amico (invio di email)
This commit is contained in:
Surya Paolo
2025-11-15 19:38:55 +01:00
parent 26a42b1f30
commit adf1aac10f
312 changed files with 12061 additions and 81773 deletions

View File

@@ -25,6 +25,7 @@ var file = `.env.${node_env}`;
// GLOBALI (Uguali per TUTTI)
process.env.LINKVERIF_REG = '/vreg';
process.env.LINK_INVITO_A_REG = '/invitetoreg';
process.env.LINK_REQUEST_NEWPASSWORD = '/requestnewpwd';
process.env.ADD_NEW_SITE = '/addNewSite';
process.env.LINK_UPDATE_PASSWORD = '/updatepassword';

View File

@@ -0,0 +1,294 @@
// telegram.controller.js
const crypto = require('crypto');
const axios = require('axios');
const { User } = require('../models/user');
// Configurazione
const TELEGRAM_BOT_TOKEN = process.env.TELEGRAM_BOT_TOKEN;
const TELEGRAM_API_URL = `https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}`;
/**
* Genera un token di verifica univoco
*/
exports.generateVerificationToken = async (req, res) => {
try {
const { username, idapp } = req.body;
if (!username) {
return res.status(400).json({ error: 'Username richiesto' });
}
// Verifica che l'utente esista
const user = await User.findOne({ idapp, username });
if (!user) {
return res.status(404).json({ error: 'Utente non trovato' });
}
// Verifica se già verificato
if (user.profile?.username_telegram && user.profile?.teleg_id) {
return res.status(400).json({ error: 'Account Telegram già collegato' });
}
// Genera token univoco
const token = crypto.randomBytes(32).toString('hex');
// Salva SOLO sul database (non serve la Map in-memory!)
await User.updateOne(
{ _id: user._id },
{
$set: {
'profile.telegram_verification_token': token,
'profile.telegram_verification_expires': new Date(Date.now() + 20 * 60 * 1000),
'profile.telegram_verified': false,
},
}
);
res.json({ token });
} catch (error) {
console.error('Errore generazione token:', error);
return res.status(500).json({ error: 'Errore del server' });
}
};
/**
* Controlla se la verifica è stata completata
*/
exports.checkVerification = async (req, res) => {
try {
const { token } = req.query;
if (!token) {
return res.status(400).json({ error: 'Token richiesto' });
}
// Cerca l'utente con questo token DIRETTAMENTE sul DB
const user = await User.findOne({
'profile.telegram_verification_token': token,
});
if (!user) {
return res.status(404).json({ error: 'Token non valido', verified: false });
}
// Verifica se è scaduto
const now = new Date();
if (now > user.profile.telegram_verification_expires) {
// Pulisci il token scaduto
await User.updateOne(
{ _id: user._id },
{
$unset: {
'profile.telegram_verification_token': '',
'profile.telegram_verification_expires': '',
},
}
);
return res.status(410).json({ error: 'Token scaduto', verified: false });
}
// Controlla se è stato verificato
const verified = !!(user.profile?.teleg_id && user.profile?.username_telegram);
res.json({
verified: verified,
username_telegram: user.profile?.username_telegram || null,
teleg_id: user.profile?.teleg_id || null,
});
} catch (error) {
console.error('Errore verifica token:', error);
return res.status(500).json({ error: 'Errore del server' });
}
};
/**
* Webhook del bot Telegram
* Gestisce i messaggi /start con il token
*/
exports.telegramWebhook = async (req, res) => {
try {
const update = req.body;
// Gestisci solo messaggi con /start
if (update.message && update.message.text && update.message.text.startsWith('/start')) {
const chatId = update.message.chat.id;
const userId = update.message.from.id;
const username = update.message.from.username;
const firstName = update.message.from.first_name;
// Estrai il token dal comando /start
const parts = update.message.text.split(' ');
const token = parts[1];
if (!token) {
await sendTelegramMessage(
chatId,
"⚠️ Link di verifica non valido. Richiedi un nuovo link dall'applicazione."
);
return res.sendStatus(200);
}
// Cerca l'utente con questo token
const user = await User.findOne({
'profile.telegram_verification_token': token,
});
if (!user) {
await sendTelegramMessage(
chatId,
"❌ Token non valido o scaduto. Richiedi un nuovo link dall'applicazione."
);
return res.sendStatus(200);
}
// Verifica scadenza
const now = new Date();
if (now > user.profile.telegram_verification_expires) {
await User.updateOne(
{ _id: user._id },
{
$unset: {
'profile.telegram_verification_token': '',
'profile.telegram_verification_expires': '',
},
}
);
await sendTelegramMessage(
chatId,
"⏰ Il token è scaduto. Richiedi un nuovo link dall'applicazione."
);
return res.sendStatus(200);
}
// Verifica se già collegato
if (user.profile?.teleg_id && user.profile?.username_telegram) {
await sendTelegramMessage(chatId, '✅ Questo account è già stato verificato!');
return res.sendStatus(200);
}
// Salva i dati Telegram e rimuovi il token
await User.updateOne(
{ _id: user._id },
{
$set: {
'profile.teleg_id': userId.toString(),
'profile.username_telegram': username || firstName,
},
$unset: {
'profile.telegram_verification_token': '',
'profile.telegram_verification_expires': '',
},
}
);
// Invia messaggio di conferma
await sendTelegramMessage(
chatId,
`✅ Account verificato con successo!\n\n` +
`Il tuo Telegram è stato collegato a: ${user.username}\n\n` +
`Puoi ora tornare all'applicazione.`
);
}
res.sendStatus(200);
} catch (error) {
console.error('Errore webhook Telegram:', error);
res.sendStatus(500);
}
};
/**
* Funzione helper per inviare messaggi Telegram
*/
async function sendTelegramMessage(chatId, text) {
try {
await axios.post(`${TELEGRAM_API_URL}/sendMessage`, {
chat_id: chatId,
text: text,
parse_mode: 'HTML',
});
} catch (error) {
console.error('Errore invio messaggio Telegram:', error);
}
}
/**
* Configura il webhook di Telegram (da eseguire una volta)
*/
exports.setupWebhook = async (req, res) => {
try {
/*const webhookUrl = `${process.env.APP_URL}/api/telegram/webhook`;
const response = await axios.post(`${TELEGRAM_API_URL}/setWebhook`, {
url: webhookUrl,
allowed_updates: ['message'],
});
res.json({
success: true,
message: 'Webhook configurato',
data: response.data,
});*/
} catch (error) {
console.error('Errore setup webhook:', error);
return res.status(500).json({ error: 'Errore configurazione webhook' });
}
};
/**
* Rimuovi collegamento Telegram
*/
exports.unlinkTelegram = async (req, res) => {
try {
const userId = req.user.id; // Assumi autenticazione middleware
await User.updateOne(
{ _id: userId },
{
$unset: {
'profile.teleg_id': '',
'profile.username_telegram': '',
'profile.telegram_verification_token': '',
'profile.telegram_verification_expires': '',
},
}
);
res.json({ success: true, message: 'Telegram scollegato' });
} catch (error) {
console.error('Errore unlink Telegram:', error);
return res.status(500).json({ error: 'Errore del server' });
}
};
/**
* Salta la verifica Telegram
*/
exports.skipTelegramVerification = async (req, res) => {
try {
const { idapp } = req.body;
const user = await User.findOne({ idapp });
if (!user) {
return res.status(404).json({ error: 'Utente non trovato' });
}
await User.updateOne(
{ _id: user._id },
{
$set: {
'profile.telegram_verification_skipped': true,
},
$unset: {
'profile.telegram_verification_token': '',
'profile.telegram_verification_expires': '',
},
}
);
res.json({ success: true, message: 'Verifica Telegram saltata' });
} catch (error) {
console.error('Errore skip verifica:', error);
return res.status(500).json({ error: 'Errore del server' });
}
};

View File

Can't render this file because it is too large.

View File

@@ -118,6 +118,7 @@
"SET_ATTEND": "%s ha detto che Parteciperà all'evento: %s",
"SET_ATTEND_OTHERS": "%s e altre %s persone hanno detto che Parteciperanno all'evento: %s",
"DATEDAYONLY": "%s dalle %s alle %s",
"DATE_1DAY": "%s dalle %s",
"DATE_2DAYS": "%s dalle %s fino a %s alle %s",
"SENDMSG_ENTRA_IN_RISO_ITALIA": "Ciao %s!<br>%s che appartiene al <em>%s</em> vuole inviarti dei RIS. Per poterli ricevere dovete entrambi utilizzare il <strong>Circuito RIS Italia</strong>.",
"CLICCA_QUI": "CLICCA QUI",

124
src/middleware/authenticate.js Executable file
View File

@@ -0,0 +1,124 @@
const server_constants = require('../tools/server_constants');
var { User } = require('../models/user');
const tools = require('../tools/general');
const auth_default = (req, res, next) => {
if (req.body.keyappid === process.env.KEY_APP_ID) next();
};
const authenticateMiddleware = async (req, res, next, withUser = false, lean = false, noError = false) => {
// Wrapper per res.send che logga automaticamente
const originalSend = res.send;
res.send = function (data) {
logResponse(req, res, data);
return originalSend.call(this, data);
};
try {
const logPrefix = noError ? (withUser ? (lean ? 'WITHUSERLEAN' : 'WITHUSER') : 'NOERROR') : 'AUTH';
// Validazione token
const token = req.header('x-auth');
if (!token) {
return handleAuthFailure(req, res, next, {
code: server_constants.RIS_CODE_HTTP_INVALID_TOKEN,
message: 'TOKEN INVALIDO',
logPrefix,
noError,
});
}
// Recupera utente
const refreshToken = req.header('x-refrtok');
const user = await User.findByToken(token, 'auth', false, withUser, lean);
// Imposta dati richiesta
req.user = user.code === server_constants.RIS_CODE_OK ? user.user : null;
req.token = user.code === server_constants.RIS_CODE_OK ? token : null;
req.refreshToken = refreshToken;
req.code = user.code;
req.statuscode2 = null;
// Gestione token scaduto
if (user.code === server_constants.RIS_CODE_HTTP_FORBIDDEN_TOKEN_EXPIRED) {
return handleAuthFailure(req, res, next, {
code: server_constants.RIS_CODE_HTTP_FORBIDDEN_TOKEN_EXPIRED,
message: 'TOKEN SCADUTO',
logPrefix,
noError,
});
}
// Gestione altri errori di autenticazione
if (user.code !== server_constants.RIS_CODE_OK) {
return handleAuthFailure(req, res, next, {
code: user.code,
message: 'AUTENTICAZIONE FALLITA',
logPrefix,
noError,
});
}
next();
} catch (e) {
console.error('❌ Errore nel middleware di autenticazione:', e);
return handleAuthFailure(req, res, next, {
code: server_constants.RIS_CODE_HTTP_INVALID_TOKEN,
message: 'ERRORE INTERNO',
logPrefix: 'ERROR',
noError,
});
}
};
// Funzione helper per gestire i fallimenti di autenticazione
function handleAuthFailure(req, res, next, { code, message, logPrefix, noError }) {
req.user = null;
req.token = null;
req.code = code;
if (noError) {
req.statuscode2 = code;
console.log(` ## ${logPrefix} - ${message} (noError mode, continuing) ⚠️`);
return next();
} else {
console.log(` ## SEND RES ${logPrefix} - ${message}`);
return res.status(code).send();
}
}
// Funzione per loggare le risposte
function logResponse(req, res, data) {
const statusCode = res.statusCode;
const method = req.method;
const url = req.originalUrl || req.url;
const userId = req.user?._id || req.user?.id || 'N/A';
const emoji = statusCode >= 200 && statusCode < 300 ? '✅' : statusCode >= 400 && statusCode < 500 ? '⚠️' : '❌';
console.log(
`${emoji} [${method}] ${url} | Status: ${statusCode} | User: ${userId} | Data: ${
data ? JSON.stringify(data).substring(0, 100) : 'empty'
}`
);
}
const authenticate = (req, res, next) => authenticateMiddleware(req, res, next);
const authenticate_withUser = (req, res, next) => authenticateMiddleware(req, res, next, true);
const authenticate_withUserLean = (req, res, next) => authenticateMiddleware(req, res, next, true, true);
const authenticate_noerror = (req, res, next) => authenticateMiddleware(req, res, next, false, false, true);
const authenticate_noerror_WithUser = (req, res, next) => authenticateMiddleware(req, res, next, true, false, true);
const authenticate_noerror_WithUserLean = (req, res, next) => {
return authenticateMiddleware(req, res, next, true, true, true);
}
module.exports = {
authenticate,
authenticate_noerror,
auth_default,
authenticate_withUser,
authenticate_noerror_WithUser,
authenticate_noerror_WithUserLean,
};

View File

@@ -319,84 +319,54 @@ MyElemSchema.statics.executeQueryTable = function (idapp, params, user) {
MyElemSchema.statics.SetIdPageInsteadThePah = async function (idapp) {
const MyElem = this;
const { MyPage } = require('../models/mypage');
// Sostituisci path con IdPage
try {
// Recupera tutti i documenti di MyPage
const pages = await MyPage.find({ idapp }); // Puoi anche specificare condizioni, se necessario
const pages = await MyPage.find({ idapp });
if (pages.length === 0) {
return 'Nessuna pagina trovata per questo idapp.';
}
const bulkOps = [];
// Utilizza una mappa per accoppiare i path con i loro Id
const pathToIdMap = {};
pages.forEach((page) => {
pathToIdMap[page.path] = page._id; // Mappa il path all'ID del documento MyPage
});
// Aggiorna MyElem utilizzando la mappa
for (const [path, id] of Object.entries(pathToIdMap)) {
if (path) {
await MyElem.updateMany(
{ idapp },
{ path: path }, // Condizione per aggiornare dove il path corrisponde
{
$set: {
idPage: id,
oldpath: path,
if (page.path) {
// Aggiorna documenti con 'path'
bulkOps.push({
updateMany: {
filter: { idapp: idapp, path: page.path },
update: {
$set: { idPage: page._id, oldpath: page.path },
$unset: { path: '' },
},
$unset: { path: '' }, // Rimuove il campo path
} // Imposta IdPage all'ID del documento corrispondente
);
},
});
// Aggiorna documenti con 'oldpath' ma senza 'idPage'
bulkOps.push({
updateMany: {
filter: {
idapp: idapp,
oldpath: page.path,
idPage: { $exists: false },
},
update: { $set: { idPage: page._id } },
},
});
}
}
if (false) {
// Utilizza una mappa per accoppiare i path con i loro Id
const pathToIdMap2 = {};
pages.forEach((page) => {
pathToIdMap2[page.path] = page._id.toString(); // Mappa il path all'ID del documento MyPage
});
// Aggiorna MyElem utilizzando la mappa
for (const [path, id] of Object.entries(pathToIdMap2)) {
await MyElem.updateMany(
{ oldpath: path }, // Condizione per aggiornare dove il path corrisponde
{
$unset: { idPage: '' }, // Rimuove il campo path
} // Imposta IdPage all'ID del documento corrispondente
);
}
for (const [oldpath, id] of Object.entries(pathToIdMap2)) {
await MyElem.updateMany(
{ oldpath: oldpath }, // Condizione per aggiornare dove il path corrisponde
{
$set: { idPage: id },
} // Imposta IdPage all'ID del documento corrispondente
);
}
}
const pathToIdMap2 = {};
pages.forEach((page) => {
pathToIdMap2[page.path] = page._id.toString(); // Mappa il path all'ID del documento MyPage
});
for (const [oldpath, id] of Object.entries(pathToIdMap2)) {
await MyElem.updateMany(
{ idapp },
{ oldpath: oldpath }, // Condizione per aggiornare dove il path corrisponde
{
$set: { idPage: id },
} // Imposta IdPage all'ID del documento corrispondente
);
if (bulkOps.length > 0) {
const result = await MyElem.bulkWrite(bulkOps);
console.log(`Aggiornati ${result.modifiedCount} documenti.`);
return `Aggiornamenti effettuati: ${result.modifiedCount} documenti.`;
}
console.log('Aggiornamenti effettuati con successo.');
return 'Aggiornamenti effettuati con successo.';
return 'Nessun documento da aggiornare.';
} catch (error) {
console.error("Errore durante l'aggiornamento:", error);
return "Errore durante l'aggiornamento:", error;
throw error;
}
};

Some files were not shown because too many files have changed in this diff Show More