mirror of
https://codeberg.org/anoncontributorxmr/monero.git
synced 2024-12-03 16:23:29 +01:00
Add more specific RPC error codes
This commit is contained in:
parent
8d511f3c24
commit
fab3b7221b
@ -341,8 +341,7 @@ namespace tools
|
|||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
|
handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR);
|
||||||
er.message = e.what();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -369,8 +368,7 @@ namespace tools
|
|||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
|
handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR);
|
||||||
er.message = e.what();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -406,8 +404,7 @@ namespace tools
|
|||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
|
handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR);
|
||||||
er.message = e.what();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -436,8 +433,7 @@ namespace tools
|
|||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
|
handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR);
|
||||||
er.message = e.what();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -454,8 +450,7 @@ namespace tools
|
|||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
|
handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR);
|
||||||
er.message = e.what();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -476,8 +471,7 @@ namespace tools
|
|||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
|
handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR);
|
||||||
er.message = e.what();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -492,8 +486,7 @@ namespace tools
|
|||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
|
handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR);
|
||||||
er.message = e.what();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -618,7 +611,7 @@ namespace tools
|
|||||||
// reject proposed transactions if there are more than one. see on_transfer_split below.
|
// reject proposed transactions if there are more than one. see on_transfer_split below.
|
||||||
if (ptx_vector.size() != 1)
|
if (ptx_vector.size() != 1)
|
||||||
{
|
{
|
||||||
er.code = WALLET_RPC_ERROR_CODE_GENERIC_TRANSFER_ERROR;
|
er.code = WALLET_RPC_ERROR_CODE_TX_TOO_LARGE;
|
||||||
er.message = "Transaction would be too large. try /transfer_split.";
|
er.message = "Transaction would be too large. try /transfer_split.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -642,22 +635,9 @@ namespace tools
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
catch (const tools::error::daemon_busy& e)
|
|
||||||
{
|
|
||||||
er.code = WALLET_RPC_ERROR_CODE_DAEMON_IS_BUSY;
|
|
||||||
er.message = e.what();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
er.code = WALLET_RPC_ERROR_CODE_GENERIC_TRANSFER_ERROR;
|
handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_GENERIC_TRANSFER_ERROR);
|
||||||
er.message = e.what();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
catch (...)
|
|
||||||
{
|
|
||||||
er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
|
|
||||||
er.message = "WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR";
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -725,22 +705,9 @@ namespace tools
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
catch (const tools::error::daemon_busy& e)
|
|
||||||
{
|
|
||||||
er.code = WALLET_RPC_ERROR_CODE_DAEMON_IS_BUSY;
|
|
||||||
er.message = e.what();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
er.code = WALLET_RPC_ERROR_CODE_GENERIC_TRANSFER_ERROR;
|
handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_GENERIC_TRANSFER_ERROR);
|
||||||
er.message = e.what();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
catch (...)
|
|
||||||
{
|
|
||||||
er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
|
|
||||||
er.message = "WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR";
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -782,22 +749,9 @@ namespace tools
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
catch (const tools::error::daemon_busy& e)
|
|
||||||
{
|
|
||||||
er.code = WALLET_RPC_ERROR_CODE_DAEMON_IS_BUSY;
|
|
||||||
er.message = e.what();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
er.code = WALLET_RPC_ERROR_CODE_GENERIC_TRANSFER_ERROR;
|
handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_GENERIC_TRANSFER_ERROR);
|
||||||
er.message = e.what();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
catch (...)
|
|
||||||
{
|
|
||||||
er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
|
|
||||||
er.message = "WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR";
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -852,22 +806,9 @@ namespace tools
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
catch (const tools::error::daemon_busy& e)
|
|
||||||
{
|
|
||||||
er.code = WALLET_RPC_ERROR_CODE_DAEMON_IS_BUSY;
|
|
||||||
er.message = e.what();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
er.code = WALLET_RPC_ERROR_CODE_GENERIC_TRANSFER_ERROR;
|
handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_GENERIC_TRANSFER_ERROR);
|
||||||
er.message = e.what();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
catch (...)
|
|
||||||
{
|
|
||||||
er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
|
|
||||||
er.message = "WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR";
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -897,10 +838,9 @@ namespace tools
|
|||||||
res.payment_id = epee::string_tools::pod_to_hex(payment_id);
|
res.payment_id = epee::string_tools::pod_to_hex(payment_id);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
catch (const std::exception &e)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
|
handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR);
|
||||||
er.message = e.what();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -929,10 +869,9 @@ namespace tools
|
|||||||
res.payment_id = epee::string_tools::pod_to_hex(info.payment_id);
|
res.payment_id = epee::string_tools::pod_to_hex(info.payment_id);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
catch (const std::exception &e)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
|
handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR);
|
||||||
er.message = e.what();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -954,8 +893,7 @@ namespace tools
|
|||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
|
handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR);
|
||||||
er.message = e.what();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -1185,8 +1123,7 @@ namespace tools
|
|||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
|
handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR);
|
||||||
er.message = e.what();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -1258,8 +1195,7 @@ namespace tools
|
|||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
|
handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR);
|
||||||
er.message = e.what();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -1494,10 +1430,9 @@ namespace tools
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
catch (...)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
|
handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR);
|
||||||
er.message = "Failed";
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1550,10 +1485,9 @@ namespace tools
|
|||||||
res.height = height;
|
res.height = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
catch (...)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
|
handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR);
|
||||||
er.message = "Failed";
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1730,10 +1664,9 @@ namespace tools
|
|||||||
m_wallet->rescan_spent();
|
m_wallet->rescan_spent();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
catch (const std::exception &e)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
|
handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR);
|
||||||
er.message = e.what();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -1798,7 +1731,7 @@ namespace tools
|
|||||||
{
|
{
|
||||||
if (m_wallet_dir.empty())
|
if (m_wallet_dir.empty())
|
||||||
{
|
{
|
||||||
er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
|
er.code = WALLET_RPC_ERROR_CODE_NO_WALLET_DIR;
|
||||||
er.message = "No wallet dir configured";
|
er.message = "No wallet dir configured";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1865,6 +1798,11 @@ namespace tools
|
|||||||
wal->generate(wallet_file, req.password, dummy_key, false, false);
|
wal->generate(wallet_file, req.password, dummy_key, false, false);
|
||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
|
{
|
||||||
|
handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!wal)
|
||||||
{
|
{
|
||||||
er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
|
er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
|
||||||
er.message = "Failed to generate wallet";
|
er.message = "Failed to generate wallet";
|
||||||
@ -1880,7 +1818,7 @@ namespace tools
|
|||||||
{
|
{
|
||||||
if (m_wallet_dir.empty())
|
if (m_wallet_dir.empty())
|
||||||
{
|
{
|
||||||
er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
|
er.code = WALLET_RPC_ERROR_CODE_NO_WALLET_DIR;
|
||||||
er.message = "No wallet dir configured";
|
er.message = "No wallet dir configured";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1914,13 +1852,13 @@ namespace tools
|
|||||||
command_line::add_arg(desc, arg_password);
|
command_line::add_arg(desc, arg_password);
|
||||||
po::store(po::parse_command_line(argc, argv, desc), vm2);
|
po::store(po::parse_command_line(argc, argv, desc), vm2);
|
||||||
}
|
}
|
||||||
std::unique_ptr<tools::wallet2> wal;
|
std::unique_ptr<tools::wallet2> wal = nullptr;
|
||||||
try {
|
try {
|
||||||
wal = tools::wallet2::make_from_file(vm2, wallet_file).first;
|
wal = tools::wallet2::make_from_file(vm2, wallet_file).first;
|
||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
wal = nullptr;
|
handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR);
|
||||||
}
|
}
|
||||||
if (!wal)
|
if (!wal)
|
||||||
{
|
{
|
||||||
@ -1934,6 +1872,63 @@ namespace tools
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
void wallet_rpc_server::handle_rpc_exception(const std::exception_ptr& e, epee::json_rpc::error& er, int default_error_code) {
|
||||||
|
try
|
||||||
|
{
|
||||||
|
std::rethrow_exception(e);
|
||||||
|
}
|
||||||
|
catch (const tools::error::daemon_busy& e)
|
||||||
|
{
|
||||||
|
er.code = WALLET_RPC_ERROR_CODE_DAEMON_IS_BUSY;
|
||||||
|
er.message = e.what();
|
||||||
|
}
|
||||||
|
catch (const tools::error::zero_destination& e)
|
||||||
|
{
|
||||||
|
er.code = WALLET_RPC_ERROR_CODE_ZERO_DESTINATION;
|
||||||
|
er.message = e.what();
|
||||||
|
}
|
||||||
|
catch (const tools::error::not_enough_money& e)
|
||||||
|
{
|
||||||
|
er.code = WALLET_RPC_ERROR_CODE_NOT_ENOUGH_MONEY;
|
||||||
|
er.message = e.what();
|
||||||
|
}
|
||||||
|
catch (const tools::error::tx_not_possible& e)
|
||||||
|
{
|
||||||
|
er.code = WALLET_RPC_ERROR_CODE_TX_NOT_POSSIBLE;
|
||||||
|
er.message = (boost::format(tr("Transaction not possible. Available only %s, transaction amount %s = %s + %s (fee)")) %
|
||||||
|
cryptonote::print_money(e.available()) %
|
||||||
|
cryptonote::print_money(e.tx_amount() + e.fee()) %
|
||||||
|
cryptonote::print_money(e.tx_amount()) %
|
||||||
|
cryptonote::print_money(e.fee())).str();
|
||||||
|
er.message = e.what();
|
||||||
|
}
|
||||||
|
catch (const tools::error::not_enough_outs_to_mix& e)
|
||||||
|
{
|
||||||
|
er.code = WALLET_RPC_ERROR_CODE_NOT_ENOUGH_OUTS_TO_MIX;
|
||||||
|
er.message = e.what();
|
||||||
|
}
|
||||||
|
catch (const error::file_exists& e)
|
||||||
|
{
|
||||||
|
er.code = WALLET_RPC_ERROR_CODE_WALLET_ALREADY_EXISTS;
|
||||||
|
er.message = "Cannot create wallet. Already exists.";
|
||||||
|
}
|
||||||
|
catch (const error::invalid_password& e)
|
||||||
|
{
|
||||||
|
er.code = WALLET_RPC_ERROR_CODE_INVALID_PASSWORD;
|
||||||
|
er.message = "Invalid password.";
|
||||||
|
}
|
||||||
|
catch (const std::exception& e)
|
||||||
|
{
|
||||||
|
er.code = default_error_code;
|
||||||
|
er.message = e.what();
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
|
||||||
|
er.message = "WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//------------------------------------------------------------------------------------------------------------------------------
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
|
@ -162,6 +162,7 @@ namespace tools
|
|||||||
void fill_transfer_entry(tools::wallet_rpc::transfer_entry &entry, const crypto::hash &payment_id, const tools::wallet2::payment_details &pd);
|
void fill_transfer_entry(tools::wallet_rpc::transfer_entry &entry, const crypto::hash &payment_id, const tools::wallet2::payment_details &pd);
|
||||||
bool not_open(epee::json_rpc::error& er);
|
bool not_open(epee::json_rpc::error& er);
|
||||||
uint64_t adjust_mixin(uint64_t mixin);
|
uint64_t adjust_mixin(uint64_t mixin);
|
||||||
|
void handle_rpc_exception(const std::exception_ptr& e, epee::json_rpc::error& er, int default_error_code);
|
||||||
|
|
||||||
wallet2 *m_wallet;
|
wallet2 *m_wallet;
|
||||||
std::string m_wallet_dir;
|
std::string m_wallet_dir;
|
||||||
|
@ -46,3 +46,11 @@
|
|||||||
#define WALLET_RPC_ERROR_CODE_NOT_OPEN -13
|
#define WALLET_RPC_ERROR_CODE_NOT_OPEN -13
|
||||||
#define WALLET_RPC_ERROR_CODE_ACCOUNT_INDEX_OUTOFBOUND -14
|
#define WALLET_RPC_ERROR_CODE_ACCOUNT_INDEX_OUTOFBOUND -14
|
||||||
#define WALLET_RPC_ERROR_CODE_ADDRESS_INDEX_OUTOFBOUND -15
|
#define WALLET_RPC_ERROR_CODE_ADDRESS_INDEX_OUTOFBOUND -15
|
||||||
|
#define WALLET_RPC_ERROR_CODE_TX_NOT_POSSIBLE -16
|
||||||
|
#define WALLET_RPC_ERROR_CODE_NOT_ENOUGH_MONEY -17
|
||||||
|
#define WALLET_RPC_ERROR_CODE_TX_TOO_LARGE -18
|
||||||
|
#define WALLET_RPC_ERROR_CODE_NOT_ENOUGH_OUTS_TO_MIX -19
|
||||||
|
#define WALLET_RPC_ERROR_CODE_ZERO_DESTINATION -20
|
||||||
|
#define WALLET_RPC_ERROR_CODE_WALLET_ALREADY_EXISTS -21
|
||||||
|
#define WALLET_RPC_ERROR_CODE_INVALID_PASSWORD -22
|
||||||
|
#define WALLET_RPC_ERROR_CODE_NO_WALLET_DIR -23
|
||||||
|
Loading…
Reference in New Issue
Block a user