feat: implement MoloApp plans 01-15 with integration
Full C++23 framework tree: runtime, observability, security, data, app, realtime, supervisor, clients, CLI, example plus enterprise tenancy, audit, operability, governance, supplychain. Postgres via docker compose for tests.
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
// orm_hook: Model save()/remove() reach the audit Appender through the
|
||||
// PATCHES section 2 hook. Without an installed Appender the hook no-ops;
|
||||
// with one installed, insert/update/delete append self-describing records.
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "audit/log/appender.h"
|
||||
#include "audit/log/store.h"
|
||||
#include "data/orm/model.hpp"
|
||||
|
||||
#define CHECK(c, msg) \
|
||||
if (!(c)) { \
|
||||
std::cerr << "FAIL orm_hook: " << msg << "\n"; \
|
||||
return 1; \
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
using molo::data::orm::FieldDef;
|
||||
using molo::data::orm::Model;
|
||||
|
||||
struct Item : public Model<Item> {
|
||||
static std::string table_name() { return "items"; }
|
||||
static std::string primary_key() { return "id"; }
|
||||
static std::vector<FieldDef> fields() {
|
||||
return {FieldDef::primary_key("id"), FieldDef::text("name")};
|
||||
}
|
||||
};
|
||||
|
||||
class FakeConn : public molo::data::Connection {
|
||||
public:
|
||||
molo::data::Backend backend() const override { return molo::data::Backend::Sqlite; }
|
||||
std::string backend_id() const override { return "fake"; }
|
||||
molo::data::Result exec(const molo::data::Context&,
|
||||
const molo::data::BoundStatement&) override {
|
||||
return molo::data::Result::command(0);
|
||||
}
|
||||
molo::data::Prepared prepare(const molo::data::Context&,
|
||||
const molo::data::BoundStatement&) override {
|
||||
return {};
|
||||
}
|
||||
molo::data::Result exec_prepared(const molo::data::Context&, const molo::data::Prepared&,
|
||||
const std::vector<molo::data::Value>&) override {
|
||||
return molo::data::Result::command(0);
|
||||
}
|
||||
void ping(const molo::data::Context&) override {}
|
||||
void close() override {}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
int main() {
|
||||
using namespace molo::audit::log;
|
||||
FakeConn conn;
|
||||
molo::data::Context ctx("req-1", "t1", 30);
|
||||
|
||||
// Without an installed Appender the hook no-ops (no crash, no store).
|
||||
{
|
||||
Item it;
|
||||
it.set("id", molo::data::make_int(7));
|
||||
it.set("name", molo::data::make_text("n1"));
|
||||
it.save(conn, ctx);
|
||||
it.set("name", molo::data::make_text("n2"));
|
||||
it.save(conn, ctx);
|
||||
it.remove(conn, ctx);
|
||||
}
|
||||
|
||||
MemoryStore store;
|
||||
Appender app(store);
|
||||
Appender::Install(&app);
|
||||
{
|
||||
Item it;
|
||||
it.set("id", molo::data::make_int(7));
|
||||
it.set("name", molo::data::make_text("n1"));
|
||||
it.save(conn, ctx);
|
||||
it.set("name", molo::data::make_text("n2"));
|
||||
it.save(conn, ctx);
|
||||
it.remove(conn, ctx);
|
||||
}
|
||||
Appender::Install(nullptr);
|
||||
|
||||
auto rows = store.ReadRange(1, 10);
|
||||
CHECK(rows.size() == 3, "three hook records");
|
||||
CHECK(rows[0].op == "insert" && rows[0].table == "items" && rows[0].pk == "7",
|
||||
"insert record shape");
|
||||
CHECK(rows[0].tenant == "t1" && rows[0].request_id == "req-1", "context carried");
|
||||
CHECK(rows[0].after_json.find("n1") != std::string::npos, "insert after image");
|
||||
CHECK(rows[1].op == "update", "update op");
|
||||
CHECK(rows[2].op == "delete" && rows[2].after_json.empty(), "delete op");
|
||||
CHECK(rows[2].before_json.find("n2") != std::string::npos, "delete before image");
|
||||
std::cout << "PASS orm_hook\n";
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user