Remove template PAM from class defs
This commit is contained in:
parent
e9b65c294e
commit
d035219202
@ -21,7 +21,6 @@ if(${CMAKE_VERSION} VERSION_GREATER "3.19.0")
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/rublon/pam.hpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/rublon/rublon.hpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/rublon/sign.hpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/rublon/span.hpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/rublon/utils.hpp
|
||||
)
|
||||
endif()
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "rublon/pam.hpp"
|
||||
#include "rublon/pam_action.hpp"
|
||||
#include <rublon/core_handler_interface.hpp>
|
||||
#include <rublon/utils.hpp>
|
||||
@ -13,16 +14,30 @@ class AuthenticationStep {
|
||||
std::string _tid;
|
||||
|
||||
public:
|
||||
AuthenticationStep(){}
|
||||
AuthenticationStep() {}
|
||||
AuthenticationStep(std::string systemToken, std::string tid) : _systemToken{std::move(systemToken)}, _tid{std::move(tid)} {}
|
||||
|
||||
template < typename Handler_t >
|
||||
auto fire(const CoreHandlerInterface< Handler_t > & coreHandler) const {
|
||||
// log step
|
||||
log(Info, "Starting %s step", static_cast< const Impl * >(this)->name);
|
||||
return static_cast< const Impl * >(this)->handle(coreHandler);
|
||||
}
|
||||
|
||||
template < typename Handler_t, typename PamInfo_t = LinuxPam >
|
||||
auto fire(const CoreHandlerInterface< Handler_t > & coreHandler, const PamInfo_t & pam) const {
|
||||
log(Info, "Starting %s step", static_cast< const Impl * >(this)->name);
|
||||
return static_cast< const Impl * >(this)->handle(coreHandler, pam);
|
||||
}
|
||||
|
||||
protected:
|
||||
void addSystemToken(Document & body, RapidJSONPMRAlloc & alloc) const {
|
||||
body.AddMember("systemToken", Value{this->_systemToken.c_str(), alloc}, alloc);
|
||||
}
|
||||
|
||||
void addTid(Document & body, RapidJSONPMRAlloc & alloc) const {
|
||||
body.AddMember("tid", Value{this->_tid.c_str(), alloc}, alloc);
|
||||
}
|
||||
|
||||
template < typename HandlerReturn_t >
|
||||
PamAction coreErrorHandler(const HandlerReturn_t & coreResponse) const {
|
||||
switch(coreResponse.error().errorClass) {
|
||||
@ -39,6 +54,7 @@ class AuthenticationStep {
|
||||
log(LogLevel::Error, "ErrorClass::BrokenData");
|
||||
return PamAction::decline;
|
||||
}
|
||||
return PamAction::decline;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -14,8 +14,6 @@
|
||||
|
||||
namespace rublon {
|
||||
|
||||
|
||||
|
||||
template < typename HttpHandler = CURL >
|
||||
class CoreHandler : public CoreHandlerInterface< CoreHandler< HttpHandler > > {
|
||||
std::string secretKey;
|
||||
@ -49,12 +47,12 @@ class CoreHandler : public CoreHandlerInterface< CoreHandler< HttpHandler > > {
|
||||
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";
|
||||
@ -70,7 +68,7 @@ class CoreHandler : public CoreHandlerInterface< CoreHandler< HttpHandler > > {
|
||||
log(LogLevel::Error, "CoreHandlerError::ConnectionError");
|
||||
return tl::unexpected{CoreHandlerError::ConnectionError};
|
||||
}
|
||||
|
||||
|
||||
if(not responseSigned(*response)) {
|
||||
log(LogLevel::Error, "CoreHandlerError::BadSigature");
|
||||
return tl::unexpected{CoreHandlerError::BadSigature};
|
||||
|
||||
@ -60,7 +60,7 @@ class CURL {
|
||||
curl_easy_setopt(curl.get(), CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
|
||||
curl_easy_setopt(curl.get(), CURLOPT_WRITEDATA, &response_data);
|
||||
|
||||
log(Info, "Request send uri:%s body:\n%s\n", uri.data(), request.body.c_str());
|
||||
log(Debug, "Request send uri:%s body:\n%s\n", uri.data(), request.body.c_str());
|
||||
auto res = curl_easy_perform(curl.get());
|
||||
if(res != CURLE_OK) {
|
||||
log(Error, "No response from Rublon server err:{%s}", curl_easy_strerror(res));
|
||||
|
||||
@ -8,41 +8,35 @@
|
||||
|
||||
#include <rublon/method/method_factory.hpp>
|
||||
|
||||
namespace rublon{
|
||||
class Verify{};
|
||||
}
|
||||
namespace rublon {
|
||||
class Verify {};
|
||||
} // namespace rublon
|
||||
|
||||
namespace rublon {
|
||||
template < class MethodSelect_t = MethodSelect, typename Pam_t = LinuxPam >
|
||||
class Init : public AuthenticationStep< Init< MethodSelect_t, Pam_t > > {
|
||||
using base_t = AuthenticationStep< Init< MethodSelect_t, Pam_t > >;
|
||||
|
||||
const char * apiPath = "/api/transaction/init";
|
||||
template < class MethodSelect_t = MethodSelect >
|
||||
class Init : public AuthenticationStep< Init< MethodSelect_t > > {
|
||||
using base_t = AuthenticationStep< Init< MethodSelect_t > >;
|
||||
|
||||
protected:
|
||||
Pam_t & _pamInfo;
|
||||
const char * apiPath = "/api/transaction/init";
|
||||
|
||||
public:
|
||||
const char * name = "Initialization";
|
||||
|
||||
Init(Pam_t & pamHandler, const rublon::Configuration & config)
|
||||
: base_t(config.parameters.systemToken, ""), _pamInfo{pamHandler} {}
|
||||
|
||||
Init(const rublon::Configuration & config) : base_t(config.parameters.systemToken, "") {}
|
||||
|
||||
/// TODO add core handler interface
|
||||
template < typename Hander_t >
|
||||
tl::expected< MethodSelect_t, PamAction > handle(const CoreHandlerInterface< Hander_t > & coreHandler) const {
|
||||
char _buffer[1024];
|
||||
std::pmr::monotonic_buffer_resource mr{_buffer, 1024};
|
||||
|
||||
RapidJSONPMRAlloc alloc{&mr};
|
||||
template < typename Hander_t, typename PamInfo_t = LinuxPam >
|
||||
tl::expected< MethodSelect_t, PamAction > handle(const CoreHandlerInterface< Hander_t > & coreHandler, const PamInfo_t & pam) const {
|
||||
RapidJSONPMRStackAlloc< 1024 > alloc{};
|
||||
Document body{rapidjson::kObjectType, &alloc};
|
||||
|
||||
body.AddMember("systemToken", Value{this->_systemToken.c_str(), alloc}, alloc);
|
||||
body.AddMember("username", Value{this->_pamInfo.username().get(), alloc}, alloc);
|
||||
|
||||
this->addSystemToken(body, alloc);
|
||||
|
||||
body.AddMember("username", Value{pam.username().get(), alloc}, alloc);
|
||||
body.AddMember("userEmail", "bwi@rublon.com", alloc); /// TODO proper username
|
||||
|
||||
Value params{rapidjson::kObjectType};
|
||||
params.AddMember("userIP", Value{_pamInfo.ip().get(), alloc}, alloc);
|
||||
params.AddMember("userIP", Value{pam.ip().get(), alloc}, alloc);
|
||||
params.AddMember("appVer", "v.1.6", alloc); /// TODO add version to cmake
|
||||
params.AddMember("os", "Ubuntu 23.04", alloc); /// TODO add version to cmake
|
||||
|
||||
@ -58,8 +52,6 @@ class Init : public AuthenticationStep< Init< MethodSelect_t, Pam_t > > {
|
||||
} else {
|
||||
return tl::unexpected{this->coreErrorHandler(coreResponse)};
|
||||
}
|
||||
|
||||
return tl::unexpected{PamAction::decline};
|
||||
}
|
||||
};
|
||||
} // namespace rublon
|
||||
|
||||
@ -13,6 +13,7 @@ struct RapidJSONPMRAlloc {
|
||||
static constexpr auto objectOffset = alignof(std::max_align_t);
|
||||
static constexpr auto memPadding = objectOffset * 2;
|
||||
|
||||
RapidJSONPMRAlloc(std::pmr::memory_resource * mr = std::pmr::get_default_resource()) : upstream{mr} {}
|
||||
void * Malloc(size_t size) {
|
||||
if(size != 0) {
|
||||
const auto allocated_size = size + memPadding;
|
||||
@ -69,9 +70,19 @@ struct RapidJSONPMRAlloc {
|
||||
}
|
||||
};
|
||||
|
||||
using Document = rapidjson::GenericDocument< rapidjson::UTF8<>, RapidJSONPMRAlloc >;
|
||||
using Value = rapidjson::GenericValue< rapidjson::UTF8<>, RapidJSONPMRAlloc >;
|
||||
template < std::size_t N >
|
||||
struct RapidJSONPMRStackAlloc : public RapidJSONPMRAlloc {
|
||||
private:
|
||||
char _buffer[N];
|
||||
std::pmr::monotonic_buffer_resource mr{_buffer, N};
|
||||
|
||||
public:
|
||||
RapidJSONPMRStackAlloc() : RapidJSONPMRAlloc(&mr) {}
|
||||
};
|
||||
|
||||
using Document = rapidjson::GenericDocument< rapidjson::UTF8<>, RapidJSONPMRAlloc >;
|
||||
using Value = rapidjson::GenericValue< rapidjson::UTF8<>, RapidJSONPMRAlloc >;
|
||||
using StringBuffer = rapidjson::GenericStringBuffer< rapidjson::UTF8<>, RapidJSONPMRAlloc >;
|
||||
using Writer = rapidjson::Writer< StringBuffer, rapidjson::UTF8<>, rapidjson::UTF8<>, RapidJSONPMRAlloc >;
|
||||
using Writer = rapidjson::Writer< StringBuffer, rapidjson::UTF8<>, rapidjson::UTF8<>, RapidJSONPMRAlloc >;
|
||||
|
||||
} // namespace rublon
|
||||
|
||||
@ -6,54 +6,40 @@
|
||||
#include <rublon/pam.hpp>
|
||||
#include <rublon/pam_action.hpp>
|
||||
|
||||
namespace rublon {
|
||||
class Confirmation {};
|
||||
}; // namespace rublon
|
||||
|
||||
namespace rublon::method {
|
||||
|
||||
template < typename PamInfo_t = LinuxPam >
|
||||
class OTP : public AuthenticationStep< OTP< PamInfo_t > > {
|
||||
using base_t = AuthenticationStep< OTP< PamInfo_t > >;
|
||||
const char * uri = "/api/transaction/confirmCode";
|
||||
|
||||
protected:
|
||||
const PamInfo_t & _pamInfo;
|
||||
class OTP : public AuthenticationStep< OTP > {
|
||||
using base_t = AuthenticationStep< OTP >;
|
||||
const char * uri = "/api/transaction/confirmCode";
|
||||
|
||||
public:
|
||||
const char * name = "One Time Password";
|
||||
const char * name = "TOTP";
|
||||
|
||||
OTP(std::string systemToken, std::string tid, const PamInfo_t & pam) : base_t(std::move(systemToken), std::move(tid)), _pamInfo{pam} {}
|
||||
|
||||
template < typename Hander_t >
|
||||
tl::expected< Confirmation, PamAction > handle(const CoreHandlerInterface< Hander_t > & coreHandler) const {
|
||||
log(Debug, "OTP fired");
|
||||
|
||||
const auto passcode =
|
||||
_pamInfo.scan([](const char * userInput) { return std::string{userInput}; }, "Mobile TOTP from Rublon Authenticator:");
|
||||
|
||||
char _buffer[1024];
|
||||
std::pmr::monotonic_buffer_resource mr{_buffer, 1024};
|
||||
|
||||
RapidJSONPMRAlloc alloc{&mr};
|
||||
OTP(std::string systemToken, std::string tid) : base_t(std::move(systemToken), std::move(tid)) {}
|
||||
|
||||
template < typename Hander_t, typename PamInfo_t = LinuxPam >
|
||||
tl::expected< AuthenticationStatus, PamAction > handle(const CoreHandlerInterface< Hander_t > & coreHandler,
|
||||
const PamInfo_t & pam) const {
|
||||
RapidJSONPMRStackAlloc< 1024 > alloc{};
|
||||
Document body{rapidjson::kObjectType, &alloc};
|
||||
|
||||
body.AddMember("systemToken", Value{this->_systemToken.c_str(), alloc}, alloc);
|
||||
body.AddMember("tid", Value{this->_tid.c_str(), alloc}, alloc);
|
||||
|
||||
this->addSystemToken(body, alloc);
|
||||
this->addTid(body, alloc);
|
||||
|
||||
const auto passcode =
|
||||
pam.scan([](const char * userInput) { return std::string{userInput}; }, "Mobile TOTP from Rublon Authenticator:");
|
||||
|
||||
body.AddMember("vericode", Value{passcode.value().c_str(), alloc}, alloc); /// TODO proper username
|
||||
|
||||
|
||||
auto coreResponse = coreHandler.request(uri, body);
|
||||
|
||||
|
||||
if(coreResponse.has_value()) {
|
||||
log(LogLevel::Info, "[TMP] has response, processing", __PRETTY_FUNCTION__);
|
||||
const auto & rublonResponse = coreResponse.value()["result"];
|
||||
std::string tid = rublonResponse["tid"].GetString();
|
||||
// {"status":"OK","result":true}
|
||||
return tl::unexpected{PamAction::accept};
|
||||
} else {
|
||||
return tl::unexpected{this->coreErrorHandler(coreResponse)};
|
||||
}
|
||||
|
||||
return tl::unexpected{PamAction::accept};
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -1,8 +1,45 @@
|
||||
#pragma once
|
||||
|
||||
#include <tl/expected.hpp>
|
||||
|
||||
#include <rublon/authentication_step_interface.hpp>
|
||||
#include <rublon/pam.hpp>
|
||||
#include <rublon/pam_action.hpp>
|
||||
|
||||
namespace rublon::method {
|
||||
class SMS {
|
||||
|
||||
class SMS : public AuthenticationStep< SMS > {
|
||||
using base_t = AuthenticationStep< SMS >;
|
||||
const char * uri = "/api/transaction/confirmCode";
|
||||
|
||||
public:
|
||||
const char * name = "SMS";
|
||||
|
||||
SMS(std::string systemToken, std::string tid) : base_t(std::move(systemToken), std::move(tid)) {}
|
||||
|
||||
template < typename Hander_t, typename PamInfo_t = LinuxPam >
|
||||
tl::expected< AuthenticationStatus, PamAction > handle(const CoreHandlerInterface< Hander_t > & coreHandler,
|
||||
const PamInfo_t & pam) const {
|
||||
RapidJSONPMRStackAlloc< 1024 > alloc{};
|
||||
Document body{rapidjson::kObjectType, &alloc};
|
||||
|
||||
this->addSystemToken(body, alloc);
|
||||
this->addTid(body, alloc);
|
||||
|
||||
const auto passcode = pam.scan([](const char * userInput) { return std::string{userInput}; }, "SMS passcode:");
|
||||
|
||||
body.AddMember("vericode", Value{passcode.value().c_str(), alloc}, alloc);
|
||||
|
||||
auto coreResponse = coreHandler.request(uri, body);
|
||||
|
||||
if(coreResponse.has_value()) {
|
||||
const auto & rublonResponse = coreResponse.value()["result"];
|
||||
// {"status":"OK","result":true}
|
||||
return tl::unexpected{PamAction::accept};
|
||||
} else {
|
||||
return tl::unexpected{this->coreErrorHandler(coreResponse)};
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace rublon::method
|
||||
|
||||
@ -13,93 +13,51 @@
|
||||
|
||||
namespace rublon {
|
||||
|
||||
template < typename Pam_t = LinuxPam >
|
||||
class Method : AuthenticationStep< Method< Pam_t > > {
|
||||
std::string _systemToken;
|
||||
std::string _tid;
|
||||
class Method : public AuthenticationStep< Method > {
|
||||
using base_t = AuthenticationStep< Method >;
|
||||
|
||||
public:
|
||||
template < typename Method_t >
|
||||
Method(Method_t && metho, std::string systemToken, std::string tid) : _impl{metho}, _systemToken{systemToken}, _tid{tid} {}
|
||||
|
||||
template < typename Handler_t >
|
||||
tl::expected< Confirmation, PamAction > fire(const CoreHandlerInterface< Handler_t > & coreHandler) const {
|
||||
log(Debug, "method select");
|
||||
|
||||
char _buffer[1024];
|
||||
std::pmr::monotonic_buffer_resource mr{_buffer, 1024};
|
||||
|
||||
RapidJSONPMRAlloc alloc{&mr};
|
||||
Document body{rapidjson::kObjectType, &alloc};
|
||||
|
||||
body.AddMember("systemToken", Value{_systemToken.c_str(), alloc}, alloc);
|
||||
body.AddMember("tid", Value{_tid.c_str(), alloc}, alloc);
|
||||
body.AddMember("method", Value{"totp", alloc}, alloc);
|
||||
body.AddMember("GDPRAccepted", Value{"true", alloc}, alloc);
|
||||
body.AddMember("tosAccepted", Value{"true", alloc}, alloc);
|
||||
|
||||
auto coreResponse = coreHandler.request("/api/transaction/methodSSH", body);
|
||||
|
||||
if(coreResponse.has_value()) {
|
||||
log(LogLevel::Info, "[TMP] has response, processing", __PRETTY_FUNCTION__);
|
||||
const auto & rublonResponse = coreResponse.value()["result"];
|
||||
std::string tid = rublonResponse["tid"].GetString();
|
||||
return tl::unexpected{PamAction::accept};
|
||||
} else {
|
||||
// mostly connectio errors
|
||||
switch(coreResponse.error().errorClass) {
|
||||
case CoreHandlerError::ErrorClass::BadSigature:
|
||||
log(LogLevel::Error, "ErrorClass::BadSigature");
|
||||
return tl::unexpected{PamAction::decline};
|
||||
case CoreHandlerError::ErrorClass::CoreException: /// TODO exception handling
|
||||
log(LogLevel::Error, "ErrorClass::CoreException");
|
||||
return tl::unexpected{PamAction::decline}; /// TODO accept?
|
||||
case CoreHandlerError::ErrorClass::ConnectionError:
|
||||
log(LogLevel::Error, "ErrorClass::ConnectionError");
|
||||
return tl::unexpected{PamAction::decline}; /// TODO decline?
|
||||
case CoreHandlerError::ErrorClass::BrokenData:
|
||||
log(LogLevel::Error, "ErrorClass::BrokenData");
|
||||
return tl::unexpected{PamAction::decline};
|
||||
}
|
||||
}
|
||||
Method(Method_t method, std::string systemToken, std::string tid) : base_t(std::move(systemToken), std::move(tid)), _impl{method} {}
|
||||
|
||||
template < typename Handler_t, typename PamInfo_t = LinuxPam >
|
||||
tl::expected< AuthenticationStatus, PamAction > fire(const CoreHandlerInterface< Handler_t > & coreHandler,
|
||||
const PamInfo_t & pam) const {
|
||||
return std::visit(
|
||||
[&](const auto & method) {
|
||||
rublon::log(LogLevel::Info, "Using '%s' method", method.name);
|
||||
return method.fire(coreHandler);
|
||||
return method.fire(coreHandler, pam);
|
||||
},
|
||||
_impl);
|
||||
}
|
||||
|
||||
private:
|
||||
std::variant< method::OTP< Pam_t > > _impl;
|
||||
std::variant< method::OTP, method::SMS > _impl;
|
||||
};
|
||||
|
||||
template < typename Pam_t = LinuxPam >
|
||||
class PostMethod : public rublon::AuthenticationStep< PostMethod< Pam_t > > {
|
||||
using base_t = rublon::AuthenticationStep< PostMethod< Pam_t > >;
|
||||
|
||||
const char * uri = "/api/transaction/methodSSH";
|
||||
class PostMethod : public rublon::AuthenticationStep< PostMethod > {
|
||||
using base_t = rublon::AuthenticationStep< PostMethod >;
|
||||
|
||||
const char * uri = "/api/transaction/methodSSH";
|
||||
std::string _method;
|
||||
|
||||
|
||||
public:
|
||||
const char * name = "Confirm Method";
|
||||
|
||||
|
||||
PostMethod(std::string systemToken, std::string tid, std::string method)
|
||||
: base_t(std::move(systemToken), std::move(tid)), _method{method} {}
|
||||
|
||||
template < typename Hander_t >
|
||||
tl::expected< Method<>, PamAction > handle(const CoreHandlerInterface< Hander_t > & coreHandler) const {
|
||||
char _buffer[1024];
|
||||
std::pmr::monotonic_buffer_resource mr{_buffer, 1024};
|
||||
RapidJSONPMRAlloc alloc{&mr};
|
||||
template < typename Hander_t, typename PamInfo_t = LinuxPam >
|
||||
tl::expected< Method, PamAction > handle(const CoreHandlerInterface< Hander_t > & coreHandler) const {
|
||||
RapidJSONPMRStackAlloc< 1024 > alloc{};
|
||||
Document body{rapidjson::kObjectType, &alloc};
|
||||
|
||||
body.AddMember("systemToken", Value{this->_systemToken.c_str(), alloc}, alloc);
|
||||
body.AddMember("tid", Value{this->_tid.c_str(), alloc}, alloc);
|
||||
|
||||
this->addSystemToken(body, alloc);
|
||||
this->addTid(body, alloc);
|
||||
|
||||
body.AddMember("method", Value{_method.c_str(), alloc}, alloc);
|
||||
body.AddMember("GDPRAccepted", Value{"true", alloc}, alloc);
|
||||
body.AddMember("tosAccepted", Value{"true", alloc}, alloc);
|
||||
body.AddMember("GDPRAccepted", "true", alloc);
|
||||
body.AddMember("tosAccepted", "true", alloc);
|
||||
|
||||
auto coreResponse = coreHandler.request(uri, body);
|
||||
|
||||
@ -107,7 +65,12 @@ class PostMethod : public rublon::AuthenticationStep< PostMethod< Pam_t > > {
|
||||
log(LogLevel::Info, "[TMP] has response, processing", __PRETTY_FUNCTION__);
|
||||
const auto & rublonResponse = coreResponse.value()["result"];
|
||||
std::string tid = rublonResponse["tid"].GetString();
|
||||
return tl::unexpected{PamAction::accept};
|
||||
|
||||
if(_method == "totp") {
|
||||
return Method{method::OTP{this->_systemToken, this->_tid}, this->_systemToken, this->_tid};
|
||||
} else if(_method == "sms") {
|
||||
return Method{method::SMS{this->_systemToken, this->_tid}, this->_systemToken, this->_tid};
|
||||
}
|
||||
} else {
|
||||
return tl::unexpected{this->coreErrorHandler(coreResponse)};
|
||||
}
|
||||
@ -131,7 +94,7 @@ class MethodSelect {
|
||||
}
|
||||
|
||||
template < typename Pam_t >
|
||||
tl::expected< PostMethod< Pam_t >, PamAction > create(const Pam_t & pam, const std::string & tid) const {
|
||||
tl::expected< PostMethod, PamAction > create(Pam_t & pam) const {
|
||||
std::pmr::map< int, std::string > methods_id;
|
||||
pam.print("%s", "");
|
||||
int i{};
|
||||
@ -171,7 +134,7 @@ class MethodSelect {
|
||||
"you selected: %s", methods_id.count(methodid.value_or(0)) ? methods_id.at(methodid.value_or(0)).c_str() : "unknown option");
|
||||
|
||||
if(methods_id.at(methodid.value_or(0)) == "totp") {
|
||||
return PostMethod< Pam_t >{systemToken, tid, methods_id.at(methodid.value_or(0))};
|
||||
return PostMethod{systemToken, _tid, methods_id.at(methodid.value_or(0))};
|
||||
}
|
||||
|
||||
return tl::unexpected{PamAction::accept};
|
||||
|
||||
@ -49,9 +49,9 @@ class LinuxPam {
|
||||
void print(const char * fmt, Ti... ti) const noexcept {
|
||||
pam_prompt(pamh, PAM_TEXT_INFO, nullptr, fmt, std::forward< Ti >(ti)...);
|
||||
}
|
||||
|
||||
|
||||
template < typename Fun, typename... Ti >
|
||||
[[nodiscard]] auto scan(Fun && f, const char * fmt, Ti... ti) const noexcept {
|
||||
auto scan(Fun && f, const char * fmt, Ti... ti) const noexcept {
|
||||
char * responseBuffer = nullptr;
|
||||
pam_prompt(pamh, PAM_PROMPT_ECHO_ON, &responseBuffer, fmt, std::forward< Ti >(ti)...);
|
||||
if(responseBuffer) {
|
||||
@ -61,5 +61,6 @@ class LinuxPam {
|
||||
}
|
||||
return std::optional< std::result_of_t< Fun(char *) > >();
|
||||
}
|
||||
|
||||
};
|
||||
} // namespace rublon
|
||||
|
||||
@ -1,5 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
namespace rublon{
|
||||
namespace rublon {
|
||||
|
||||
enum class PamAction { accept, decline };
|
||||
}
|
||||
|
||||
class AuthenticationStatus {};
|
||||
|
||||
|
||||
} // namespace rublon
|
||||
|
||||
@ -12,9 +12,6 @@
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <variant>
|
||||
|
||||
#include <rublon/method/method_factory.hpp>
|
||||
|
||||
@ -1,329 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <array> // for std::array, etc.
|
||||
#include <cassert> // for assert
|
||||
#include <cstddef> // for std::size_t, etc.
|
||||
#include <iterator> // for std::reverse_iterator, etc.
|
||||
#include <type_traits> // for std::enable_if, etc.
|
||||
|
||||
namespace rublon {
|
||||
|
||||
#define CONSTRAINT(...) std::enable_if_t< (__VA_ARGS__), int > = 0
|
||||
#define EXPECTS(...) assert((__VA_ARGS__))
|
||||
|
||||
// constants
|
||||
|
||||
// equivalent to std::numeric_limits<std::size_t>::max()
|
||||
inline constexpr std::size_t dynamic_extent = -1;
|
||||
|
||||
// class template span
|
||||
|
||||
template < class T, std::size_t N = dynamic_extent >
|
||||
class span;
|
||||
|
||||
namespace span_detail {
|
||||
|
||||
// detect specializations of span
|
||||
|
||||
template < class T >
|
||||
struct is_span : std::false_type {};
|
||||
|
||||
template < class T, std::size_t N >
|
||||
struct is_span< span< T, N > > : std::true_type {};
|
||||
|
||||
template < class T >
|
||||
inline constexpr bool is_span_v = is_span< T >::value;
|
||||
|
||||
// detect specializations of std::array
|
||||
|
||||
template < class T >
|
||||
struct is_array : std::false_type {};
|
||||
|
||||
template < class T, std::size_t N >
|
||||
struct is_array< std::array< T, N > > : std::true_type {};
|
||||
|
||||
template < class T >
|
||||
inline constexpr bool is_array_v = is_array< T >::value;
|
||||
|
||||
// ADL-aware data() and size()
|
||||
|
||||
template < class C >
|
||||
constexpr decltype(auto) my_data(C & c) {
|
||||
return std::data(c);
|
||||
}
|
||||
|
||||
template < class C >
|
||||
constexpr decltype(auto) my_size(C & c) {
|
||||
return std::size(c);
|
||||
}
|
||||
|
||||
// detect container
|
||||
|
||||
template < class C, class = void >
|
||||
struct is_cont : std::false_type {};
|
||||
|
||||
template < class C >
|
||||
struct is_cont< C,
|
||||
std::void_t< std::enable_if_t< !is_span_v< C > >,
|
||||
std::enable_if_t< !is_array_v< C > >,
|
||||
std::enable_if_t< !std::is_array_v< C > >,
|
||||
decltype(std::data(std::declval< C >())),
|
||||
decltype(std::size(std::declval< C >())) > > : std::true_type {};
|
||||
|
||||
template < class C >
|
||||
inline constexpr bool is_cont_v = is_cont< C >::value;
|
||||
} // namespace span_detail
|
||||
|
||||
template < class T, std::size_t N >
|
||||
class span {
|
||||
public:
|
||||
// constants and types
|
||||
|
||||
using element_type = T;
|
||||
using value_type = std::remove_cv_t< T >;
|
||||
using index_type = std::size_t;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
|
||||
using pointer = T *;
|
||||
using const_pointer = const T *;
|
||||
using reference = T &;
|
||||
using const_reference = const T &;
|
||||
|
||||
using iterator = T *;
|
||||
using const_iterator = const T *;
|
||||
using reverse_iterator = std::reverse_iterator< iterator >;
|
||||
using const_reverse_iterator = std::reverse_iterator< const_iterator >;
|
||||
|
||||
static constexpr index_type extent = N;
|
||||
|
||||
// constructors, copy, and assignment
|
||||
|
||||
// LWG 3198 applied
|
||||
constexpr span() noexcept : size_{0}, data_{nullptr} {
|
||||
static_assert(N == dynamic_extent || N == 0);
|
||||
}
|
||||
|
||||
constexpr span(T * ptr, index_type n) : size_{n}, data_{ptr} {
|
||||
EXPECTS(N == dynamic_extent || N == n);
|
||||
}
|
||||
|
||||
constexpr span(T * first, T * last) : size_{last - first}, data_{first} {
|
||||
EXPECTS(N == dynamic_extent || last - first = N);
|
||||
}
|
||||
|
||||
template < std::size_t M,
|
||||
CONSTRAINT(N == dynamic_extent ||
|
||||
N == M &&
|
||||
std::is_convertible_v< std::remove_pointer_t< decltype(span_detail::my_data(std::declval< T (&)[M] >())) > (*)[], T (*)[] >) >
|
||||
constexpr span(T (&arr)[M]) noexcept : size_{M}, data_{arr} {}
|
||||
|
||||
template < std::size_t M,
|
||||
CONSTRAINT(N == dynamic_extent ||
|
||||
N == M &&
|
||||
std::is_convertible_v< std::remove_pointer_t< decltype(span_detail::my_data(std::declval< T (&)[M] >())) > (*)[], T (*)[] >) >
|
||||
constexpr span(std::array< value_type, M > & arr) noexcept : size_{M}, data_{arr.data()} {}
|
||||
|
||||
template < std::size_t M,
|
||||
CONSTRAINT(N == dynamic_extent ||
|
||||
N == M &&
|
||||
std::is_convertible_v< std::remove_pointer_t< decltype(span_detail::my_data(std::declval< T (&)[M] >())) > (*)[], T (*)[] >) >
|
||||
constexpr span(const std::array< value_type, M > & arr) noexcept : size_{M}, data_{arr.data()} {}
|
||||
|
||||
template < class Cont,
|
||||
CONSTRAINT(N == dynamic_extent && span_detail::is_cont_v< Cont > &&
|
||||
std::is_convertible_v< std::remove_pointer_t< decltype(span_detail::my_data(std::declval< Cont >())) > (*)[], T (*)[] >) >
|
||||
constexpr span(Cont & c) : size_{span_detail::my_size(c)}, data_{span_detail::my_data(c)} {}
|
||||
|
||||
template < class Cont,
|
||||
CONSTRAINT(N == dynamic_extent && span_detail::is_cont_v< Cont > &&
|
||||
std::is_convertible_v< std::remove_pointer_t< decltype(span_detail::my_data(std::declval< Cont >())) > (*)[], T (*)[] >) >
|
||||
constexpr span(const Cont & c) : size_{span_detail::my_size(c)}, data_{span_detail::my_data(c)} {}
|
||||
|
||||
constexpr span(const span & other) noexcept = default;
|
||||
|
||||
// template < class U, std::size_t M, CONSTRAINT(N == dynamic_extent || N == M && std::is_convertible_v< U (*)[], T (*)[] >) >
|
||||
// constexpr span(const span< U, M > & s) noexcept : size_{s.size()}, data_{s.data()} {}
|
||||
|
||||
~span() noexcept = default;
|
||||
|
||||
constexpr span & operator=(const span & other) noexcept = default;
|
||||
|
||||
// subviews
|
||||
|
||||
template < std::size_t Cnt >
|
||||
constexpr span< T, Cnt > first() const {
|
||||
assert(Cnt <= size());
|
||||
return {data(), Cnt};
|
||||
}
|
||||
|
||||
template < std::size_t Cnt >
|
||||
constexpr span< T, Cnt > last() const {
|
||||
assert(Cnt <= size());
|
||||
return {data() + (size() - Cnt), Cnt};
|
||||
}
|
||||
|
||||
template < std::size_t Off, std::size_t Cnt = dynamic_extent >
|
||||
constexpr auto subspan() const {
|
||||
assert(Off <= size() && (Cnt == dynamic_extent || Off + Cnt <= size()));
|
||||
if constexpr(Cnt != dynamic_extent)
|
||||
return span< T, Cnt >{data() + Off, Cnt};
|
||||
else if constexpr(N != dynamic_extent)
|
||||
return span< T, N - Off >{data() + Off, size() - Off};
|
||||
else
|
||||
return span< T, dynamic_extent >{data() + Off, size() - Off};
|
||||
}
|
||||
|
||||
constexpr span< T, dynamic_extent > first(index_type cnt) const {
|
||||
assert(cnt <= size());
|
||||
return {data(), cnt};
|
||||
}
|
||||
|
||||
constexpr span< T, dynamic_extent > last(index_type cnt) const {
|
||||
assert(cnt <= size());
|
||||
return {data() + (size() - cnt), cnt};
|
||||
}
|
||||
|
||||
constexpr span< T, dynamic_extent > subspan(index_type off, index_type cnt = dynamic_extent) const {
|
||||
assert(off <= size() && (cnt == dynamic_extent || off + cnt <= size()));
|
||||
return {data() + off, cnt == dynamic_extent ? size() - off : cnt};
|
||||
}
|
||||
|
||||
// observers
|
||||
|
||||
constexpr index_type size() const noexcept {
|
||||
return size_;
|
||||
}
|
||||
|
||||
constexpr index_type size_bytes() const noexcept {
|
||||
return size() * sizeof(T);
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr bool empty() const noexcept {
|
||||
return size() == 0;
|
||||
}
|
||||
|
||||
// element access
|
||||
|
||||
constexpr reference operator[](index_type idx) const {
|
||||
assert(idx < size());
|
||||
return *(data() + idx);
|
||||
}
|
||||
|
||||
constexpr reference front() const {
|
||||
assert(!empty());
|
||||
return *data();
|
||||
}
|
||||
|
||||
constexpr reference back() const {
|
||||
assert(!empty());
|
||||
return *(data() + (size() - 1));
|
||||
}
|
||||
|
||||
constexpr pointer data() const noexcept {
|
||||
return data_;
|
||||
}
|
||||
|
||||
// iterator support
|
||||
|
||||
constexpr iterator begin() const noexcept {
|
||||
return data();
|
||||
}
|
||||
|
||||
constexpr iterator end() const noexcept {
|
||||
return data() + size();
|
||||
}
|
||||
|
||||
constexpr const_iterator cbegin() const noexcept {
|
||||
return data();
|
||||
}
|
||||
|
||||
constexpr const_iterator cend() const noexcept {
|
||||
return data() + size();
|
||||
}
|
||||
|
||||
constexpr reverse_iterator rbegin() const noexcept {
|
||||
return reverse_iterator{end()};
|
||||
}
|
||||
|
||||
constexpr reverse_iterator rend() const noexcept {
|
||||
return reverse_iterator{begin()};
|
||||
}
|
||||
|
||||
constexpr const_reverse_iterator crbegin() const noexcept {
|
||||
return reverse_iterator{cend()};
|
||||
}
|
||||
|
||||
constexpr const_reverse_iterator crend() const noexcept {
|
||||
return reverse_iterator{cbegin()};
|
||||
}
|
||||
|
||||
friend constexpr iterator begin(span s) noexcept {
|
||||
return s.begin();
|
||||
}
|
||||
|
||||
friend constexpr iterator end(span s) noexcept {
|
||||
return s.end();
|
||||
}
|
||||
|
||||
private:
|
||||
pointer data_;
|
||||
index_type size_;
|
||||
};
|
||||
|
||||
// deduction guide
|
||||
|
||||
template < class T, std::size_t N >
|
||||
span(T (&)[N]) -> span< T, N >;
|
||||
|
||||
template < class T, std::size_t N >
|
||||
span(std::array< T, N > &) -> span< T, N >;
|
||||
|
||||
template < class T, std::size_t N >
|
||||
span(const std::array< T, N > &) -> span< const T, N >;
|
||||
|
||||
template < class Cont >
|
||||
span(Cont &) -> span< typename Cont::value_type >;
|
||||
|
||||
template < class Cont >
|
||||
span(const Cont &) -> span< const typename Cont::value_type >;
|
||||
|
||||
// views of objects representation
|
||||
|
||||
template < class T, std::size_t N >
|
||||
auto as_bytes(span< T, N > s) noexcept -> span< const std::byte, N == dynamic_extent ? dynamic_extent : sizeof(T) * N > {
|
||||
return {reinterpret_cast< const std::byte * >(s.data()), s.size_bytes()};
|
||||
}
|
||||
|
||||
template < class T, std::size_t N, CONSTRAINT(!std::is_const_v< T >) >
|
||||
auto as_writable_bytes(span< T, N > s) noexcept -> span< std::byte, N == dynamic_extent ? dynamic_extent : sizeof(T) * N > {
|
||||
return {reinterpret_cast< std::byte * >(s.data()), s.size_bytes()};
|
||||
}
|
||||
} // namespace rublon
|
||||
|
||||
namespace std {
|
||||
|
||||
// tuple interface
|
||||
// the primary template declarations are included in <array>
|
||||
|
||||
template < class T, std::size_t N >
|
||||
struct tuple_size< rublon::span< T, N > > : std::integral_constant< std::size_t, N > {};
|
||||
|
||||
// not defined
|
||||
template < class T >
|
||||
struct tuple_size< rublon::span< T, rublon::dynamic_extent > >;
|
||||
|
||||
template < std::size_t I, class T, std::size_t N >
|
||||
struct tuple_element< I, rublon::span< T, N > > {
|
||||
static_assert(N != rublon::dynamic_extent && I < N);
|
||||
using type = T;
|
||||
};
|
||||
|
||||
template < std::size_t I, class T, std::size_t N >
|
||||
constexpr T & get(rublon::span< T, N > s) noexcept {
|
||||
static_assert(N != rublon::dynamic_extent && I < N);
|
||||
return s[I];
|
||||
}
|
||||
} // namespace std
|
||||
|
||||
#undef CONSTRAINT
|
||||
#undef EXPECTS
|
||||
@ -6,11 +6,10 @@
|
||||
|
||||
#include <rapidjson/rapidjson.h>
|
||||
|
||||
#include <rublon/init.hpp>
|
||||
#include <rublon/pam.hpp>
|
||||
#include <rublon/rublon.hpp>
|
||||
#include <rublon/utils.hpp>
|
||||
#include <rublon/pam.hpp>
|
||||
|
||||
#include <rublon/init.hpp>
|
||||
|
||||
#define DLL_PUBLIC __attribute__((visibility("default")))
|
||||
|
||||
@ -39,29 +38,26 @@ DLL_PUBLIC int pam_sm_acct_mgmt([[maybe_unused]] pam_handle_t * pamh,
|
||||
|
||||
DLL_PUBLIC int
|
||||
pam_sm_authenticate(pam_handle_t * pamh, [[maybe_unused]] int flags, [[maybe_unused]] int argc, [[maybe_unused]] const char ** argv) {
|
||||
rublon::log(rublon::LogLevel::Debug, "pam start");
|
||||
using namespace rublon;
|
||||
|
||||
auto rublonConfig = rublon::ConfigurationFactory{}.systemConfig();
|
||||
auto rublonConfig = ConfigurationFactory{}.systemConfig();
|
||||
|
||||
rublon::CoreHandler CH{rublonConfig.value()};
|
||||
rublon::LinuxPam pam{pamh};
|
||||
CoreHandler CH{rublonConfig.value()};
|
||||
LinuxPam pam{pamh};
|
||||
|
||||
auto selectMethod = [&](const rublon::MethodSelect & selector) { return selector.create(pam, std::string{""}); };
|
||||
auto confirmMethod = [&](const rublon::PostMethod<rublon::LinuxPam> & confirm) { return confirm.fire(CH); };
|
||||
auto selectMethod = [&](const MethodSelect & selector) { return selector.create(pam); };
|
||||
auto confirmMethod = [&](const PostMethod & confirm) { return confirm.fire(CH); };
|
||||
auto verifi = [&](const Method & method) { return method.fire(CH, pam); };
|
||||
|
||||
auto method = rublon::Init{pam, rublonConfig.value()}
|
||||
.fire(CH) //
|
||||
.and_then(selectMethod)
|
||||
.and_then(confirmMethod);
|
||||
auto authStatus = Init{rublonConfig.value()}
|
||||
.fire(CH, pam) //
|
||||
.and_then(selectMethod)
|
||||
.and_then(confirmMethod)
|
||||
.and_then(verifi);
|
||||
|
||||
method.value().fire(CH);
|
||||
|
||||
rublon::log(rublon::LogLevel::Debug, "Method");
|
||||
|
||||
method.value().fire(CH);
|
||||
|
||||
// .and_then([](const auto & value) { return tl::expected< rublon::Configuration, rublon::PamAction >{}; }) //
|
||||
// .and_then([](const auto & conf) { return tl::expected< rublon::Configuration, rublon::PamAction >{}; });
|
||||
if(authStatus.has_value()) {
|
||||
rublon::log(rublon::Info, "Auth OK");
|
||||
}
|
||||
|
||||
return PAM_SUCCESS;
|
||||
}
|
||||
|
||||
@ -20,5 +20,11 @@ FetchContent_MakeAvailable(
|
||||
googletest
|
||||
googlebenchmark)
|
||||
|
||||
add_executable(rublon-tests utilsTests.cpp rublonTests.cpp core_handler_tests.cpp init_test.cpp method_factory_test.cpp)
|
||||
add_executable(rublon-tests
|
||||
authentication_step_common_tests.cpp
|
||||
utilsTests.cpp
|
||||
rublonTests.cpp
|
||||
core_handler_tests.cpp
|
||||
init_test.cpp method_factory_test.cpp
|
||||
)
|
||||
target_link_libraries(rublon-tests rublon-ssh GTest::gmock_main -lssl -lcrypto)
|
||||
|
||||
4
PAM/ssh/tests/authentication_step_common_tests.cpp
Normal file
4
PAM/ssh/tests/authentication_step_common_tests.cpp
Normal file
@ -0,0 +1,4 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
|
||||
#include <rublon/authentication_step_interface.hpp>
|
||||
@ -27,12 +27,12 @@ class CoreHandlerMock : public CoreHandlerInterface< CoreHandlerMock > {
|
||||
gen.generateBrokenData = true;
|
||||
return *this;
|
||||
}
|
||||
|
||||
CoreHandlerMock & methods(std::initializer_list<std::string> methods) {
|
||||
|
||||
CoreHandlerMock & methods(std::initializer_list< std::string > methods) {
|
||||
gen.methods(methods);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
CoreHandlerMock & tid(std::string tid) {
|
||||
gen.tid(tid);
|
||||
return *this;
|
||||
@ -62,20 +62,12 @@ class PamInfoMock {
|
||||
|
||||
class MethodFactoryMock {
|
||||
public:
|
||||
using MethodFactoryCreate_t = tl::expected< Method<PamInfoMock>, PamAction >;
|
||||
|
||||
template<typename ... Args>
|
||||
MethodFactoryMock(Args && ... ) {}
|
||||
using MethodFactoryCreate_t = tl::expected< Method, PamAction >;
|
||||
|
||||
MOCK_METHOD(MethodFactoryCreate_t, create, (const PamInfoMock&, std::string tid), (const));
|
||||
};
|
||||
template < typename... Args >
|
||||
MethodFactoryMock(Args &&...) {}
|
||||
|
||||
class InitTestable : public Init< MethodFactoryMock, PamInfoMock > {
|
||||
public:
|
||||
InitTestable(PamInfoMock&pam, const rublon::Configuration & conf) : Init{pam, conf} {}
|
||||
PamInfoMock & pam() {
|
||||
return _pamInfo;
|
||||
}
|
||||
MOCK_METHOD(MethodFactoryCreate_t, create, (const PamInfoMock &, std::string tid), (const));
|
||||
};
|
||||
|
||||
class RublonHttpInitTest : public testing::Test {
|
||||
@ -84,15 +76,15 @@ class RublonHttpInitTest : public testing::Test {
|
||||
EXPECT_CALL(pam, ip()).WillOnce(Return("192.168.0.1"));
|
||||
EXPECT_CALL(pam, username()).WillOnce(Return("bwi"));
|
||||
}
|
||||
|
||||
RublonHttpInitTest() : coreHandler{}, pam{}, sut{pam, conf}{
|
||||
|
||||
RublonHttpInitTest() : coreHandler{}, pam{}, sut{conf} {
|
||||
expectDefaultPamInfo();
|
||||
}
|
||||
|
||||
CoreHandlerMock coreHandler;
|
||||
PamInfoMock pam;
|
||||
InitTestable sut;
|
||||
// MethodFactoryMock &methodFactoryMock;
|
||||
Init< MethodFactoryMock > sut;
|
||||
// MethodFactoryMock &methodFactoryMock;
|
||||
};
|
||||
|
||||
using CoreReturn = tl::expected< Document, CoreHandlerError >;
|
||||
@ -100,7 +92,7 @@ using CoreReturn = tl::expected< Document, CoreHandlerError >;
|
||||
TEST_F(RublonHttpInitTest, initializationSendsRequestOnGoodPath) {
|
||||
EXPECT_CALL(coreHandler, request("/api/transaction/init", _))
|
||||
.WillOnce(Return(tl::unexpected{CoreHandlerError{CoreHandlerError::BadSigature}}));
|
||||
sut.handle(coreHandler);
|
||||
sut.handle(coreHandler, pam);
|
||||
}
|
||||
|
||||
MATCHER_P(HoldsPamAction, action, "") {
|
||||
@ -109,26 +101,27 @@ MATCHER_P(HoldsPamAction, action, "") {
|
||||
|
||||
TEST_F(RublonHttpInitTest, rublon_Accept_pamLoginWhenThereIsNoConnection) {
|
||||
EXPECT_CALL(coreHandler, request(_, _)).WillOnce(Return(tl::unexpected{CoreHandlerError{CoreHandlerError::ConnectionError}}));
|
||||
EXPECT_THAT(sut.handle(coreHandler), HoldsPamAction(PamAction::decline));
|
||||
EXPECT_THAT(sut.handle(coreHandler, pam), HoldsPamAction(PamAction::decline));
|
||||
}
|
||||
|
||||
TEST_F(RublonHttpInitTest, rublon_Decline_pamLoginWhenServerHasBadSignature) {
|
||||
EXPECT_CALL(coreHandler, request(_, _)).WillOnce(Return(tl::unexpected{CoreHandlerError{CoreHandlerError::BadSigature}}));
|
||||
EXPECT_THAT(sut.handle(coreHandler), HoldsPamAction(PamAction::decline));
|
||||
EXPECT_THAT(sut.handle(coreHandler, pam), HoldsPamAction(PamAction::decline));
|
||||
}
|
||||
|
||||
TEST_F(RublonHttpInitTest, rublon_Decline_pamLoginWhenServerReturnsBrokenData) {
|
||||
EXPECT_CALL(coreHandler, request(_, _)).WillOnce(Return(tl::unexpected{CoreHandlerError{CoreHandlerError::BrokenData}}));
|
||||
EXPECT_THAT(sut.handle(coreHandler), HoldsPamAction(PamAction::decline));
|
||||
EXPECT_THAT(sut.handle(coreHandler, pam), HoldsPamAction(PamAction::decline));
|
||||
}
|
||||
|
||||
TEST_F(RublonHttpInitTest, rublon_Decline_pamLoginWhenServerReturnsCoreException) {
|
||||
EXPECT_CALL(coreHandler, request(_, _)).WillOnce(Return(tl::unexpected{CoreHandlerError{CoreHandlerError::CoreException}}));
|
||||
EXPECT_THAT(sut.handle(coreHandler), HoldsPamAction(PamAction::decline));
|
||||
EXPECT_THAT(sut.handle(coreHandler, pam), HoldsPamAction(PamAction::decline));
|
||||
}
|
||||
|
||||
TEST_F(RublonHttpInitTest, AllNeededInformationNeedsToBePassedToMethodFactory) {
|
||||
EXPECT_CALL(coreHandler, request(_, _)).WillOnce(Return(coreHandler.statusPending().methods({"sms", "otp"}).tid("transaction ID").create()));
|
||||
// EXPECT_CALL(methodFactoryMock, create_mocked(_,"transaction ID") );
|
||||
sut.handle(coreHandler);
|
||||
EXPECT_CALL(coreHandler, request(_, _))
|
||||
.WillOnce(Return(coreHandler.statusPending().methods({"sms", "otp"}).tid("transaction ID").create()));
|
||||
// EXPECT_CALL(methodFactoryMock, create_mocked(_,"transaction ID") );
|
||||
sut.handle(coreHandler, pam);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user