Webhooks for New Accounts (#79)

This commit is contained in:
Lee *!* Clagett
2023-08-23 16:07:37 -04:00
committed by Lee *!* Clagett
parent 524e26e1a4
commit aa171b77c3
13 changed files with 434 additions and 222 deletions

View File

@@ -29,6 +29,7 @@
#include <cstring>
#include <memory>
#include "db/string.h"
#include "wire.h"
#include "wire/crypto.h"
#include "wire/json/write.h"
@@ -215,7 +216,7 @@ namespace db
namespace
{
constexpr const char* map_webhook_type[] = {"tx-confirmation"};
constexpr const char* map_webhook_type[] = {"tx-confirmation", "new-account"};
template<typename F, typename T>
void map_webhook_key(F& format, T& self)
@@ -292,6 +293,15 @@ namespace db
);
}
void write_bytes(wire::writer& dest, const webhook_new_account& self)
{
wire::object(dest,
wire::field<0>("event_id", std::cref(self.value.first.event_id)),
wire::field<1>("token", std::cref(self.value.second.token)),
wire::field<2>("address", address_string(self.account))
);
}
bool operator<(const webhook_dupsort& left, const webhook_dupsort& right) noexcept
{
return left.payment_id == right.payment_id ?

View File

@@ -252,7 +252,8 @@ namespace db
enum class webhook_type : std::uint8_t
{
tx_confirmation = 0,
tx_confirmation = 0, // cannot change values - stored in DB
new_account
// unconfirmed_tx,
// new_block
// confirmed_tx,
@@ -316,6 +317,14 @@ namespace db
};
void write_bytes(wire::json_writer&, const webhook_event&);
//! Returned by DB when a webhook event "tripped"
struct webhook_new_account
{
webhook_value value;
account_address account;
};
void write_bytes(wire::writer&, const webhook_new_account&);
bool operator==(transaction_link const& left, transaction_link const& right) noexcept;
bool operator<(transaction_link const& left, transaction_link const& right) noexcept;
bool operator<=(transaction_link const& left, transaction_link const& right) noexcept;

View File

@@ -1635,14 +1635,14 @@ namespace db
});
}
expect<void> storage::creation_request(account_address const& address, crypto::secret_key const& key, account_flags flags) noexcept
expect<std::vector<webhook_new_account>> storage::creation_request(account_address const& address, crypto::secret_key const& key, account_flags flags) noexcept
{
MONERO_PRECOND(db != nullptr);
if (!db->create_queue_max)
return {lws::error::create_queue_max};
return db->try_write([this, &address, &key, flags] (MDB_txn& txn) -> expect<void>
return db->try_write([this, &address, &key, flags] (MDB_txn& txn) -> expect<std::vector<webhook_new_account>>
{
const expect<db::account_time> current_time = get_account_time();
if (!current_time)
@@ -1651,10 +1651,12 @@ namespace db
cursor::accounts_by_address accounts_ba_cur;
cursor::blocks blocks_cur;
cursor::accounts requests_cur;
cursor::webhooks webhooks_cur;
MONERO_CHECK(check_cursor(txn, this->db->tables.accounts_ba, accounts_ba_cur));
MONERO_CHECK(check_cursor(txn, this->db->tables.blocks, blocks_cur));
MONERO_CHECK(check_cursor(txn, this->db->tables.requests, requests_cur));
MONERO_CHECK(check_cursor(txn, this->db->tables.webhooks, webhooks_cur));
MDB_val keyv = lmdb::to_val(by_address_version);
MDB_val value = lmdb::to_val(address);
@@ -1709,7 +1711,24 @@ namespace db
if (err)
return {lmdb::error(err)};
return success();
std::vector<webhook_new_account> hooks{};
webhook_key wkey{account_id::invalid, webhook_type::new_account};
keyv = lmdb::to_val(wkey);
err = mdb_cursor_get(webhooks_cur.get(), &keyv, &value, MDB_SET_KEY);
for (;;)
{
if (err)
{
if (err == MDB_NOTFOUND)
break;
return {lmdb::error(err)};
}
hooks.push_back(webhook_new_account{MONERO_UNWRAP(webhooks.get_value(value)), address});
err = mdb_cursor_get(webhooks_cur.get(), &keyv, &value, MDB_NEXT_DUP);
}
return hooks;
});
}
@@ -2190,7 +2209,7 @@ namespace db
});
}
expect<void> storage::add_webhook(const webhook_type type, const account_address& address, const webhook_value& event)
expect<void> storage::add_webhook(const webhook_type type, const boost::optional<account_address>& address, const webhook_value& event)
{
if (event.second.url != "zmq")
{
@@ -2210,10 +2229,13 @@ namespace db
MONERO_CHECK(check_cursor(txn, this->db->tables.webhooks, webhooks_cur));
webhook_key key{account_id::invalid, type};
MDB_val lmkey = lmdb::to_val(by_address_version);
MDB_val lmvalue = lmdb::to_val(address);
MDB_val lmkey{};
MDB_val lmvalue{};
if (address)
{
lmkey = lmdb::to_val(by_address_version);
lmvalue = lmdb::to_val(*address);
const int err = mdb_cursor_get(accounts_ba_cur.get(), &lmkey, &lmvalue, MDB_GET_BOTH);
if (err && err != MDB_NOTFOUND)
return {lmdb::error(err)};

View File

@@ -212,7 +212,7 @@ namespace db
rescan(block_id height, epee::span<const account_address> addresses);
//! Add an account for later approval. For use with the login endpoint.
expect<void> creation_request(account_address const& address, crypto::secret_key const& key, account_flags flags) noexcept;
expect<std::vector<webhook_new_account>> creation_request(account_address const& address, crypto::secret_key const& key, account_flags flags) noexcept;
/*!
Request lock height of an existing account. No effect if the `start_height`
@@ -249,12 +249,12 @@ namespace db
\param type The webhook event type to be tracked by the DB.
\param address is required for `type == tx_confirmation`, and is not
not needed for all other types (use default construction of zeroes).
not needed for all other types.
\param event Additional information for the webhook. A valid "http"
or "https" URL must be provided (or else error). All other information
is optional.
*/
expect<void> add_webhook(webhook_type type, const account_address& address, const webhook_value& event);
expect<void> add_webhook(webhook_type type, const boost::optional<account_address>& address, const webhook_value& event);
/*! Delete all webhooks associated with every value in `addresses`. This is
likely only valid for `tx_confirmation` event types. */