rublon-ssh/PAM/ssh/include/rublon/CoreHandler.hpp
2023-07-21 10:55:06 +02:00

112 lines
3.6 KiB
C++

#pragma once
#include <memory_resource>
#include <string>
#include "configuration.hpp"
#include "curl.hpp"
#include "json.hpp"
#include "sign.hpp"
#include <tl/expected.hpp>
namespace rublon {
class CoreHandlerError {
public:
enum ErrorClass { BadSigature, CoreException, ConnectionError, BrokenData };
CoreHandlerError(ErrorClass e) : errorClass{e} {}
CoreHandlerError(ErrorClass e, std::string r) : errorClass{e}, reson{std::move(r)} {}
ErrorClass errorClass;
std::string reson;
};
template < typename Impl >
class CoreHandlerInterface {
public:
tl::expected< rublon::Document, CoreHandlerError > request(std::string_view path, const rublon::Document & body) const {
rublon::debugLog("[TMP] request",__PRETTY_FUNCTION__);
return static_cast< const Impl * >(this)->request(path, body);
}
};
template < typename HttpHandler = CURL >
class CoreHandler : public CoreHandlerInterface< CoreHandler< HttpHandler > > {
std::string secretKey;
std::string url;
std::pmr::string xRublonSignature(std::pmr::memory_resource & mr, std::string_view body) const {
return {signData(body, secretKey.c_str()).data(), &mr};
}
void signRequest(std::pmr::monotonic_buffer_resource & mr, Request & request) const {
rublon::debugLog("[TMP]",__PRETTY_FUNCTION__);
request.headers["X-Rublon-Signature"] = xRublonSignature(mr, request.body);
}
bool responseSigned(const Response & response) const {
rublon::debugLog("[TMP]",__PRETTY_FUNCTION__);
const auto & xRubResp = response.headers.at("x-rublon-signature");
const auto & sign = signData(response.body, secretKey);
return xRubResp == sign.data();
}
protected:
HttpHandler http{};
public:
void debugLog(const char *, const char *) {}
CoreHandler(const rublon::Configuration & config) : secretKey{config.parameters.secretKey}, url{config.parameters.apiServer} {}
tl::expected< rublon::Document, CoreHandlerError > request(std::string_view path, const rublon::Document & body) const {
rublon::debugLog("[TMP] request",__PRETTY_FUNCTION__);
std::byte _buffer[16 * 1024];
std::pmr::monotonic_buffer_resource mr{_buffer, sizeof(_buffer)};
rublon::RapidJSONPMRAlloc alloc{&mr};
rublon::StringBuffer jsonStr{&alloc};
rublon::Writer writer{jsonStr, &alloc};
body.Accept(writer);
Request request;
request.headers["Content-Type"] = "application/json";
request.headers["Accept"] = "application/json";
request.body = jsonStr.GetString();
rublon::debugLog("[TMP] request", "sign");
signRequest(mr, request);
// std::pmr::string uri{url + path.data(), &mr};
// rublon::debugLog("[TMP] send", request.body.c_str());
// auto response = http.request(uri, request);
// if(not response.has_value()) {
return tl::unexpected{CoreHandlerError::ConnectionError};
// }
// if(not responseSigned(*response)) {
// return tl::unexpected{CoreHandlerError::BadSigature};
// }
// rublon::Document resp{&alloc};
// resp.Parse(response->body.c_str());
// if(resp.HasParseError() or not resp.HasMember("result")) {
// return tl::unexpected{CoreHandlerError::BrokenData};
// }
// if(resp["result"].HasMember("exception")) {
// return tl::unexpected{CoreHandlerError{CoreHandlerError::CoreException, resp["result"]["exception"].GetString()}};
// }
// return resp;
}
};
} // namespace rublon