"Riregistrarsi se l'invitante non ha ancora confermato l'invito.
Annullo la richiesta precedente. (inviando un msg di annullamento. (Si è già registrato con un alto invito.)"
This commit is contained in:
@@ -546,7 +546,7 @@ UserSchema.statics.findByTokenAnyAccess = function(token) {
|
||||
});
|
||||
};
|
||||
|
||||
UserSchema.statics.findByCredentials = function(idapp, username, password) {
|
||||
UserSchema.statics.findByCredentials = function(idapp, username, password, pwdcrypted) {
|
||||
const User = this;
|
||||
let pwd = '';
|
||||
|
||||
@@ -571,7 +571,7 @@ UserSchema.statics.findByCredentials = function(idapp, username, password) {
|
||||
$or: [
|
||||
{deleted: {$exists: false}},
|
||||
{deleted: {$exists: true, $eq: false}}],
|
||||
});
|
||||
}).lean();
|
||||
} else {
|
||||
return !user.deleted || (user.deleted && user.subaccount) ? user : null;
|
||||
}
|
||||
@@ -581,6 +581,14 @@ UserSchema.statics.findByCredentials = function(idapp, username, password) {
|
||||
|
||||
pwd = user.password;
|
||||
|
||||
if (pwdcrypted) {
|
||||
if (pwd === user.password){
|
||||
return user
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
// Use bcrypt.compare to compare password and user.password
|
||||
// console.log("pwd1 " + password);
|
||||
@@ -596,7 +604,7 @@ UserSchema.statics.findByCredentials = function(idapp, username, password) {
|
||||
});
|
||||
};
|
||||
|
||||
UserSchema.statics.findByUsername = async function(idapp, username, alsoemail) {
|
||||
UserSchema.statics.findByUsername = async function(idapp, username, alsoemail, onlyifVerifiedByAportador) {
|
||||
const User = this;
|
||||
|
||||
const myreg = ['^', username, '$'].join('');
|
||||
@@ -621,6 +629,16 @@ UserSchema.statics.findByUsername = async function(idapp, username, alsoemail) {
|
||||
});
|
||||
}
|
||||
return ris;
|
||||
}).then((rec) => {
|
||||
if (onlyifVerifiedByAportador) {
|
||||
if (tools.getAskToVerifyReg(idapp)) {
|
||||
if (!rec.verified_by_aportador)
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return rec;
|
||||
});
|
||||
};
|
||||
|
||||
@@ -910,6 +928,24 @@ UserSchema.statics.setnotask_verif = async function(
|
||||
return !!myrec;
|
||||
};
|
||||
|
||||
UserSchema.statics.setaportador_solidario = async function(
|
||||
idapp, username, usernameAportador) {
|
||||
const User = this;
|
||||
|
||||
if (username === undefined)
|
||||
return false;
|
||||
|
||||
const myquery = {
|
||||
'idapp': idapp,
|
||||
'username': username,
|
||||
};
|
||||
|
||||
const myrec = await User.findOneAndUpdate(myquery,
|
||||
{$set: {'aportador_solidario': usernameAportador}}, {new: false});
|
||||
|
||||
return !!myrec;
|
||||
};
|
||||
|
||||
UserSchema.statics.setVerifiedByAportadorToALL = async function() {
|
||||
|
||||
return User.updateMany({}, {$set: {'verified_by_aportador': true}},
|
||||
@@ -1035,13 +1071,23 @@ UserSchema.statics.findByLinkTokenforgot = function(idapp, email, tokenforgot) {
|
||||
});
|
||||
};
|
||||
|
||||
UserSchema.statics.findByEmail = function(idapp, email) {
|
||||
UserSchema.statics.findByEmail = function(idapp, email, onlyifVerifiedByAportador) {
|
||||
const User = this;
|
||||
|
||||
return User.findOne({
|
||||
'idapp': idapp,
|
||||
'email': email,
|
||||
$or: [{deleted: {$exists: false}}, {deleted: {$exists: true, $eq: false}}],
|
||||
}).then((rec) => {
|
||||
if (onlyifVerifiedByAportador) {
|
||||
if (tools.getAskToVerifyReg(idapp)) {
|
||||
if (!rec.verified_by_aportador)
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return rec;
|
||||
});
|
||||
};
|
||||
|
||||
@@ -3092,7 +3138,7 @@ UserSchema.statics.convSubAccount = async function(idapp) {
|
||||
UserSchema.statics.getLastRec = async function(idapp) {
|
||||
const User = this;
|
||||
|
||||
lastrec = await User.find({idapp}).sort({date_reg: -1}).limit(1);
|
||||
lastrec = await User.find({idapp}).sort({date_reg: -1}).limit(1).lean();
|
||||
if (!!lastrec) {
|
||||
return lastrec[0];
|
||||
} else {
|
||||
|
||||
@@ -21,7 +21,7 @@ router.post('/ck', (req, res) => {
|
||||
const idapp = req.body.idapp;
|
||||
var email = req.body.email;
|
||||
|
||||
User.findByEmail(idapp, email).then((user) => {
|
||||
User.findByEmail(idapp, email, true).then((user) => {
|
||||
if (!user) {
|
||||
return res.status(404).send();
|
||||
}
|
||||
|
||||
@@ -614,7 +614,7 @@ router.patch('/chval', authenticate, async (req, res) => {
|
||||
|
||||
}
|
||||
|
||||
await mytable.findByIdAndUpdate(id, {$set: fieldsvalue}).
|
||||
return await mytable.findByIdAndUpdate(id, {$set: fieldsvalue}).
|
||||
then(async (rec) => {
|
||||
// tools.mylogshow(' REC TO MODIFY: ', rec);
|
||||
if (!rec) {
|
||||
|
||||
@@ -91,7 +91,8 @@ router.post('/', async (req, res) => {
|
||||
|
||||
// tools.mylog("LANG PASSATO = " + user.lang, "IDAPP", user.idapp);
|
||||
|
||||
if (!tools.isAlphaNumericAndSpecialCharacter(body.username) || body.email.length < 6 ||
|
||||
if (!tools.isAlphaNumericAndSpecialCharacter(body.username) ||
|
||||
body.email.length < 6 ||
|
||||
body.username.length < 6 || body.password.length < 6) {
|
||||
await tools.snooze(5000);
|
||||
console.log('Username non valido in Registrazione: ' + body.username);
|
||||
@@ -156,10 +157,26 @@ router.post('/', async (req, res) => {
|
||||
// }
|
||||
let exit;
|
||||
|
||||
let utentenonancoraVerificato = false;
|
||||
|
||||
const trovarec = await User.findByCredentials(user.idapp, user.username, user.password, true);
|
||||
|
||||
// Check if already esist email or username
|
||||
exit = await User.findByUsername(user.idapp, user.username).
|
||||
then((useralreadyexist) => {
|
||||
if (useralreadyexist) {
|
||||
|
||||
if (tools.getAskToVerifyReg(useralreadyexist.idapp)) {
|
||||
if (!useralreadyexist.verified_by_aportador &&
|
||||
useralreadyexist.profile.teleg_id > 0) {
|
||||
if (trovarec) {
|
||||
utentenonancoraVerificato = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!utentenonancoraVerificato) {
|
||||
res.status(400).
|
||||
send({
|
||||
code: server_constants.RIS_CODE_USERNAME_ALREADY_EXIST,
|
||||
@@ -167,9 +184,12 @@ router.post('/', async (req, res) => {
|
||||
});
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
if (!utentenonancoraVerificato) {
|
||||
|
||||
if (exit === 1)
|
||||
return;
|
||||
|
||||
@@ -203,18 +223,11 @@ router.post('/', async (req, res) => {
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
let recextra = null;
|
||||
|
||||
// recextra = await ExtraList.findByCellAndNameSurname(user.idapp, user.profile.cell, user.name, user.surname);
|
||||
// let nomeaportador_corretto = "";
|
||||
// if (recextra) {
|
||||
// nomeaportador_corretto = recextra.aportador_solidario_name_surname;
|
||||
// if (nomeaportador_corretto === '')
|
||||
// nomeaportador_corretto = recextra.aportador_solidario_originale_name_surname;
|
||||
// }
|
||||
|
||||
const id_aportador = await User.getIdByUsername(user.idapp,
|
||||
user.aportador_solidario);
|
||||
const id_aportador = await User.getIdByUsername(user.idapp, user.aportador_solidario);
|
||||
|
||||
if (!id_aportador && tools.getAskToVerifyReg(body.idapp)) {
|
||||
// Si sta tentando di registrare una persona sotto che non corrisponde!
|
||||
@@ -230,6 +243,28 @@ router.post('/', async (req, res) => {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (utentenonancoraVerificato) {
|
||||
if (id_aportador) {
|
||||
// Se mi sono registrato ma l'invitante non mi abilita, allora il posso registrarmi nuovamente, con lo stesso username e password,
|
||||
// con un'altro link di un'altro invitante !
|
||||
await User.setaportador_solidario(user.idapp, user.username,
|
||||
user.aportador_solidario);
|
||||
|
||||
const myuser = await User.findOne({_id: trovarec._id});
|
||||
if (myuser) {
|
||||
|
||||
await telegrambot.askConfirmationUserRegistration(myuser.idapp,
|
||||
shared_consts.CallFunz.REGISTRATION, myuser,
|
||||
myuser.profile.username_telegram, myuser.profile.firstname_telegram,
|
||||
myuser.profile.lastname_telegram);
|
||||
|
||||
const token = await myuser.generateAuthToken(req);
|
||||
res.header('x-auth', token).send(myuser);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// let already_registered = (recextra || user.aportador_solidario === tools.APORTADOR_NONE) && (user.idapp === tools.AYNI);
|
||||
|
||||
// Check if is an other people aportador_solidario
|
||||
@@ -297,7 +332,7 @@ router.get('/:idapp/:username', async (req, res) => {
|
||||
// return res.status(200).send();
|
||||
// }
|
||||
|
||||
await User.findByUsername(idapp, username, false).then((user) => {
|
||||
await User.findByUsername(idapp, username, false, true).then((user) => {
|
||||
if (!user) {
|
||||
return res.status(404).send();
|
||||
}
|
||||
@@ -341,11 +376,13 @@ router.post('/profile', authenticate, (req, res) => {
|
||||
|
||||
//++Todo: controlla che tipo di dati ha il permesso di leggere
|
||||
|
||||
return User.getUserProfileByUsername(idapp, username, req.user.username, false, req.user.perm).
|
||||
return User.getUserProfileByUsername(idapp, username, req.user.username,
|
||||
false, req.user.perm).
|
||||
then((ris) => {
|
||||
|
||||
return User.getFriendsByUsername(idapp, req.user.username).then((friends) => {
|
||||
res.send({user: ris, friends });
|
||||
return User.getFriendsByUsername(idapp, req.user.username).
|
||||
then((friends) => {
|
||||
res.send({user: ris, friends});
|
||||
});
|
||||
|
||||
}).catch((e) => {
|
||||
@@ -892,7 +929,13 @@ async function eseguiDbOp(idapp, mydata, locale) {
|
||||
const globalTables = require('../tools/globalTables');
|
||||
|
||||
//++ Todo: TO FIXIT !
|
||||
const mytablesstr = ['settings', 'users', 'templemail', 'contribtypes', 'bots', 'cfgservers'];
|
||||
const mytablesstr = [
|
||||
'settings',
|
||||
'users',
|
||||
'templemail',
|
||||
'contribtypes',
|
||||
'bots',
|
||||
'cfgservers'];
|
||||
|
||||
try {
|
||||
let numrectot = 0;
|
||||
@@ -1031,7 +1074,7 @@ router.post('/dbop', authenticate, async (req, res) => {
|
||||
idapp = req.body.idapp;
|
||||
locale = req.body.locale;
|
||||
|
||||
try{
|
||||
try {
|
||||
const ris = await eseguiDbOp(idapp, mydata, locale);
|
||||
|
||||
res.send(ris);
|
||||
|
||||
@@ -495,7 +495,7 @@ const txt = {
|
||||
MSG_APORTADOR_USER_REGISTERED: emo.FIRE +
|
||||
' Si è appena Registrato "%s" (n. %s)\nInvitato da %s',
|
||||
MSG_APORTADOR_ASK_CONFIRM: '🆕💥 🧍♂️ Abilita Nuova Registrazione: %s',
|
||||
MSG_APORTADOR_CONFIRMED: '✅ %s è stato Abilitato correttamente!',
|
||||
MSG_APORTADOR_CONFIRMED: '✅ %s è stato Abilitato correttamente (da %s)!',
|
||||
MSG_APORTADOR_DEST_CONFIRMED: '✅ Sei stato Abilitato correttamente da %s!\n' +
|
||||
'Vai sulla App oppure clicca qui per entrare\n👉🏻 %s',
|
||||
MSG_APORTADOR_DEST_NOT_CONFIRMED: emo.EXCLAMATION_MARK +
|
||||
@@ -917,6 +917,72 @@ module.exports = {
|
||||
await this.sendMsgTelegramToTheManagers(mylocalsconf.idapp, addtext + text);
|
||||
},
|
||||
|
||||
askConfirmationUserRegistration: async function(
|
||||
idapp, myfunc, myuser, usernametelegram = '', name_telegram = '',
|
||||
surname_telegram = '') {
|
||||
|
||||
const cl = getclTelegByidapp(idapp);
|
||||
|
||||
try {
|
||||
|
||||
const userDest = myuser.aportador_solidario;
|
||||
const langdest = myuser.lang;
|
||||
|
||||
let keyb = null;
|
||||
let domanda = '';
|
||||
|
||||
if (myfunc === shared_consts.CallFunz.REGISTRATION) {
|
||||
const notask_verif = await User.notAsk_VerifByUsername(idapp, userDest);
|
||||
|
||||
if (notask_verif) {
|
||||
// Non chiedi la verifica Registrazione
|
||||
setVerifiedReg(myuser.idapp, myuser.lang, myuser.username, userDest);
|
||||
} else {
|
||||
|
||||
const name = myuser.username +
|
||||
(myuser.name ? `(${myuser.name} + ' ' + ${myuser.surname})` : '');
|
||||
const linkuserprof = tools.getHostByIdApp(idapp) + '/my/' +
|
||||
myuser.username;
|
||||
domanda = printf(getstr(langdest, 'MSG_APORTADOR_ASK_CONFIRM'),
|
||||
`<br>Username: <b>${name}</b><br>Profilo su APP: ${linkuserprof}<br>Email: ` +
|
||||
myuser.email);
|
||||
|
||||
if (usernametelegram) {
|
||||
domanda += '<br>Profilo su Telegram [' + name_telegram + ' ' +
|
||||
surname_telegram + ']:<br>' + 'https://t.me/' +
|
||||
usernametelegram;
|
||||
}
|
||||
|
||||
keyb = cl.getInlineKeyboard(myuser.lang, [
|
||||
{
|
||||
text: '✅ Abilita ' + myuser.username,
|
||||
callback_data: InlineConferma.RISPOSTA_SI +
|
||||
shared_consts.CallFunz.REGISTRATION + tools.SEP +
|
||||
myuser.username + tools.SEP + userDest,
|
||||
},
|
||||
{
|
||||
text: '🚫 Rifiuta ' + myuser.username,
|
||||
callback_data: InlineConferma.RISPOSTA_NO +
|
||||
shared_consts.CallFunz.REGISTRATION + tools.SEP +
|
||||
myuser.username + tools.SEP + userDest,
|
||||
},
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
// Invia Msg
|
||||
if (domanda) {
|
||||
const teleg_id = await User.TelegIdByUsername(idapp, userDest);
|
||||
await local_sendMsgTelegramByIdTelegram(idapp, teleg_id, domanda,
|
||||
undefined, undefined, true, keyb);
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
console.error('Error askConfirmationUserRegistration', e);
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
sendMsgTelegramToTheManagers: async function(
|
||||
idapp, text, onlyintofile = false, MyForm = null, nottousername = '') {
|
||||
|
||||
@@ -1365,78 +1431,13 @@ async function setVerifiedReg(idapp, lang, usernameorig, usernameDest) {
|
||||
shared_consts.FRIENDSCMD.SETFRIEND);
|
||||
|
||||
const msgDest = printf(getstr(lang, 'MSG_APORTADOR_CONFIRMED'),
|
||||
`${usernameDest}`);
|
||||
await local_sendMsgTelegram(idapp, usernameorig, msgDest);
|
||||
`${usernameorig}`, usernameDest);
|
||||
await local_sendMsgTelegram(idapp, usernameDest, msgDest);
|
||||
} catch (e) {
|
||||
console.log('e', e);
|
||||
}
|
||||
}
|
||||
|
||||
async function askConfirmationUserRegistration(
|
||||
idapp, myfunc, myuser, usernametelegram = '', name_telegram = '',
|
||||
surname_telegram = '') {
|
||||
|
||||
const cl = getclTelegByidapp(idapp);
|
||||
|
||||
try {
|
||||
|
||||
const userDest = myuser.aportador_solidario;
|
||||
const langdest = myuser.lang;
|
||||
|
||||
let keyb = null;
|
||||
let domanda = '';
|
||||
|
||||
if (myfunc === shared_consts.CallFunz.REGISTRATION) {
|
||||
const notask_verif = await User.notAsk_VerifByUsername(idapp, userDest);
|
||||
|
||||
if (notask_verif) {
|
||||
// Non chiedi la verifica Registrazione
|
||||
setVerifiedReg(myuser.idapp, myuser.lang, userDest, myuser.username);
|
||||
} else {
|
||||
|
||||
const name = myuser.username +
|
||||
(myuser.name ? `(${myuser.name} + ' ' + ${myuser.surname})` : '');
|
||||
const linkuserprof = tools.getHostByIdApp(idapp) + '/my/' +
|
||||
myuser.username;
|
||||
domanda = printf(getstr(langdest, 'MSG_APORTADOR_ASK_CONFIRM'),
|
||||
`<br>Username: <b>${name}</b><br>Profilo su APP: ${linkuserprof}<br>Email: ` +
|
||||
myuser.email);
|
||||
|
||||
if (usernametelegram) {
|
||||
domanda += '<br>Profilo su Telegram [' + name_telegram + ' ' +
|
||||
surname_telegram + ']:<br>' + 'https://t.me/' + usernametelegram;
|
||||
}
|
||||
|
||||
keyb = cl.getInlineKeyboard(myuser.lang, [
|
||||
{
|
||||
text: '✅ Abilita ' + myuser.username,
|
||||
callback_data: InlineConferma.RISPOSTA_SI +
|
||||
shared_consts.CallFunz.REGISTRATION + tools.SEP +
|
||||
myuser.username + tools.SEP + userDest,
|
||||
},
|
||||
{
|
||||
text: '🚫 Rifiuta ' + myuser.username,
|
||||
callback_data: InlineConferma.RISPOSTA_NO +
|
||||
shared_consts.CallFunz.REGISTRATION + tools.SEP +
|
||||
myuser.username + tools.SEP + userDest,
|
||||
},
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
// Invia Msg
|
||||
if (domanda) {
|
||||
const teleg_id = await User.TelegIdByUsername(idapp, userDest);
|
||||
await local_sendMsgTelegramByIdTelegram(idapp, teleg_id, domanda,
|
||||
undefined, undefined, true, keyb);
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
console.error('Error askConfirmationUserRegistration', e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function getusernameByUser(idapp, msg) {
|
||||
let username = '';
|
||||
let rec = this.getRecInMem(msg);
|
||||
@@ -1727,7 +1728,7 @@ class Telegram {
|
||||
printf(getstr(rec.user.lang, 'MSG_SET_USERNAME_OK')));
|
||||
|
||||
if (!rec.user.verified_by_aportador) {
|
||||
askConfirmationUserRegistration(this.idapp,
|
||||
this.askConfirmationUserRegistration(this.idapp,
|
||||
shared_consts.CallFunz.REGISTRATION, rec.user,
|
||||
msg.from.username || '', msg.from.first_name || '',
|
||||
msg.from.last_name || '');
|
||||
@@ -2713,7 +2714,7 @@ class Telegram {
|
||||
tools.getHostByIdApp(this.idapp)));
|
||||
|
||||
if (msg.from.username) {
|
||||
askConfirmationUserRegistration(this.idapp,
|
||||
this.askConfirmationUserRegistration(this.idapp,
|
||||
shared_consts.CallFunz.REGISTRATION, recuser,
|
||||
msg.from.username || '', msg.from.first_name || '',
|
||||
msg.from.last_name || '');
|
||||
@@ -3538,13 +3539,12 @@ class Telegram {
|
||||
async sendMsgLog(id, text, menu, form, msg_id, chat_id, ripr_menuPrec) {
|
||||
|
||||
const rec = this.getRecInMemById(id);
|
||||
const username = rec ? rec.username : ''
|
||||
const username = rec ? rec.username_bo : '';
|
||||
|
||||
console.log('Msg inviato a ', username, text);
|
||||
this.sendMsg(id, text, menu, form, msg_id, chat_id, ripr_menuPrec)
|
||||
console.log('Msg inviato a ', username, '(', id, ')', text);
|
||||
this.sendMsg(id, text, menu, form, msg_id, chat_id, ripr_menuPrec);
|
||||
}
|
||||
|
||||
|
||||
getmenuKey(mymenu, lang) {
|
||||
let mymenuout = null;
|
||||
try {
|
||||
@@ -3845,16 +3845,18 @@ if (true) {
|
||||
|
||||
await User.setZoomPresenza(user.idapp, user._id, false);
|
||||
|
||||
} else if (data.action === InlineConferma.RISPOSTA_SI +
|
||||
shared_consts.CallFunz.REGISTRATION) {
|
||||
} else if (data.action === InlineConferma.RISPOSTA_SI + shared_consts.CallFunz.REGISTRATION) {
|
||||
const changed = await myclTelegram.setCmdToUsername(rec,
|
||||
data.username,
|
||||
Cmd.VALIDATE_REGISTRATION, true);
|
||||
|
||||
if (changed) {
|
||||
await User.setFriendsCmd(user.idapp, data.username,
|
||||
userDest.username, shared_consts.FRIENDSCMD.SETFRIEND);
|
||||
|
||||
if (changed) {
|
||||
await User.setaportador_solidario(user.idapp, data.username,
|
||||
userDest.username);
|
||||
|
||||
const msgOrig = printf(
|
||||
getstr(userDest.lang, 'MSG_APORTADOR_DEST_CONFIRMED'),
|
||||
`${userDest.username}`, tools.getHostByIdApp(user.idapp));
|
||||
@@ -3870,6 +3872,7 @@ if (true) {
|
||||
|
||||
} else if (data.action === InlineConferma.RISPOSTA_NO +
|
||||
shared_consts.CallFunz.REGISTRATION) {
|
||||
if (userDest.username === user.aportador_solidario) {
|
||||
const changed = await myclTelegram.setCmdToUsername(rec,
|
||||
data.username,
|
||||
Cmd.VALIDATE_REGISTRATION, false);
|
||||
@@ -3880,7 +3883,8 @@ if (true) {
|
||||
const nomestr = tools.getNomeCognomeEUserNameByUser(user);
|
||||
|
||||
const msgOrig = printf(
|
||||
getstr(userDest.lang, 'MSG_APORTADOR_DEST_NOT_CONFIRMED',
|
||||
getstr(userDest.lang,
|
||||
'MSG_APORTADOR_DEST_NOT_CONFIRMED',
|
||||
nomeDest));
|
||||
const msgDest = printf(
|
||||
getstr(user.lang, 'MSG_APORTADOR_NOT_CONFIRMED'),
|
||||
@@ -3894,6 +3898,7 @@ if (true) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
let text;
|
||||
|
||||
Reference in New Issue
Block a user