#pragma once #include #include #include #include #include #include #include #include namespace rublon { /// TODO move to some other place using PAM = LinuxPam; using Session = SessionBase< PAM, CoreHandler< CURL > >; using Transaction = TransactionBase< Session >; } // namespace rublon extern std::string g_tid; namespace rublon { template < class MethodSelect_t = MethodSelect > class Init : public AuthenticationStep { using base_t = AuthenticationStep; const char * apiPath = "/api/transaction/init"; tl::expected< MethodSelect_t, Error > createMethod(const Document & coreResponse) const { const auto & rublonResponse = coreResponse["result"]; std::string tid = rublonResponse["tid"].GetString(); g_tid = tid; return MethodSelect_t{this->_systemToken, tid, rublonResponse["methods"], _session.config().prompt}; } template < typename PamInfo_t > void addPamInfo(Document & coreRequest, const PamInfo_t & pam) const { auto & alloc = coreRequest.GetAllocator(); coreRequest.AddMember("username", Value{pam.username().get(), alloc}, alloc); } template < typename PamInfo_t > void addParams(Document & coreRequest, const PamInfo_t & pam) const { memory::MonotonicStackResource< 512 > stackResource; std::pmr::string releaseInfo{&stackResource}; auto & alloc = coreRequest.GetAllocator(); const auto os = details::osName(&stackResource); if(os == "unknown") { log(LogLevel::Warning, "No OS information available"); } Value osNamePretty{os.data(), static_cast< unsigned >(os.size()), alloc}; Value ip{pam.ip().get(), alloc}; Value params{rapidjson::kObjectType}; params.AddMember("userIP", ip, alloc); params.AddMember("appVer", "2.0.2", alloc); /// TODO add version to cmake params.AddMember("os", osNamePretty, alloc); coreRequest.AddMember("params", std::move(params), alloc); } template tl::expected< std::reference_wrapper< const Document >, Error > checkEnrolement(const Document & coreResponse, const Pam_T pam) const { using namespace std::string_view_literals; const auto & resp = coreResponse; if(resp.HasMember("result") and resp["result"].IsObject() and resp["result"].HasMember("status")) { const auto & status = resp["result"]["status"].GetString(); log(LogLevel::Warning, "Got enrolement message with stats %s", status); if((status == "pending"sv || status == "waiting"sv) and resp["result"].HasMember("webURI")) { const auto & weburi = resp["result"]["webURI"].GetString(); pam.print("Visit %s", weburi); return tl::unexpected{Error{RublonAuthenticationInterrupt{RublonAuthenticationInterrupt::UserPending}}}; } if(status == "denied"sv) { return tl::unexpected{Error{RublonAuthenticationInterrupt{RublonAuthenticationInterrupt::UserDenied}}}; } } return coreResponse; } public: const char * name = "Initialization"; const Session & _session; Init(const Session & session) : base_t(std::string{session.config().systemToken.data(), 32}, ""), _session{session} { log(LogLevel::Debug, "Init"); } template < typename Hander_t, typename PamInfo_t = LinuxPam > [[deprecated]] tl::expected< MethodSelect_t, Error > handle(const CoreHandlerInterface< Hander_t > & coreHandler, const PamInfo_t & pam) const { const auto createMethod = [&](const auto & coreResponse) { return this->createMethod(coreResponse); }; const auto checkEnrolement = [&](const auto & coreResponse) { return this->checkEnrolement(coreResponse,pam); }; RapidJSONPMRStackAlloc< 2048 > alloc{}; Document body{rapidjson::kObjectType, &alloc}; this->addSystemToken(body); this->addPamInfo(body, pam); this->addParams(body, pam); return coreHandler .request(alloc, apiPath, body) // .and_then(checkEnrolement) .and_then(createMethod); } // tl::expected< Transaction, Error > openTransaction() const { // const auto createTransaction = [&](const auto & coreResponse) { return this->createTransaction(coreResponse); }; // const auto checkEnrolement = [&](const auto & coreResponse) { return this->checkEnrolement(coreResponse, _session.pam()); }; // RapidJSONPMRStackAlloc< 2048 > alloc{}; // Document body{rapidjson::kObjectType, &alloc}; // this->addSystemToken(body); // this->addPamInfo(body, _session.pam()); // this->addParams(body, _session.pam()); // return _session.coreHandler() // .request(alloc, apiPath, body) // // .and_then(checkEnrolement) // .and_then(createTransaction); // } }; } // namespace rublon