rublon-ssh/PAM/ssh/include/rublon/error.hpp
rublon-bwi 9415174eba
Bwi/bugfix round2 (#9)
* Fix log file access, refactor configuration reading class

* Remove bypass option in favor of failmode

* fix loging, print enrolment info

* Add EMAIL method

* Add yubi authentication method

* Add support for verification message

* Add verification

* Made changes in Vagrant's files to run different OSs

* Switch off tests and packages demands to run PAM on Debian 11

* Add authentication totp

* Changes in utils

* Remove unnessesary interface

* Changed vagrant files and postinstal script for Ubuntu 20 and 22

* Moved adding PasswordAuth to vagrant file from posinst

* Added ubuntu 24.04

* Set version

* Poprawki UI

* WebSocket implementation 

* Add totp authentication method

* fixup changes in utils

* Remove unnessesary interface and simplify code

* Remove "default" message handler from WebSocket class

* Change display names of known authentication methods

* Cleanup code in 'main' file

* Add CheckApplication

* Remove unused function

* Changed vagrant files and postinstal script for Ubuntu 20 and 22

* Moved adding PasswordAuth to vagrant file from posinst

* Added ubuntu 24.04

* Set version to 2.0.2

* Proper handle for missing configuration

* Fixup use value of optional object

* Add more vCPU/RAM to vagrant VM's + fix translations

* Minor WS fixes, translations

* Proper handler for Werification error

* Make use of prompt parameter

* Add max number of prompts

* remove unused code, fir includes

* Add Waiting status

* Add check application status check

---------

Co-authored-by: Madzik <m.w@linux.pl>
2024-05-28 12:04:20 +02:00

272 lines
8.7 KiB
C++
Executable File

#pragma once
#include <algorithm>
#include <cstddef>
#include <optional>
#include <rublon/non_owning_ptr.hpp>
#include <string_view>
#include <tl/expected.hpp>
#include <string>
#include <variant>
namespace rublon {
template < typename... Types >
constexpr std::array< std::string_view, sizeof...(Types) > make_array(Types... names) {
return {std::forward< Types >(names)...};
}
constexpr auto test = make_array("one", "two");
#define names constexpr static inline const char * errorClassPrettyName[]
class ConfigurationError {
public:
enum class ErrorClass { RequiredValueNotFound, BadFailMode, BadInput, Empty };
constexpr static auto errorClassPrettyName = make_array("RequiredValueNotFound", "BadFailMode", "BadInput", "Empty");
constexpr static auto prettyName = "Configurtion Error";
constexpr ConfigurationError(ErrorClass e = ErrorClass::RequiredValueNotFound) : errorClass{e} {}
constexpr const char * what() const {
return errorClassPrettyName[static_cast< int >(errorClass)].data();
}
ErrorClass errorClass;
};
class ConnectionError {
public:
enum ErrorClass { Timeout, HttpError, ClientError };
constexpr static auto errorClassPrettyName = make_array("Timeout", "Error", "Client Error");
constexpr static auto prettyName = "Connection Error";
constexpr ConnectionError() : errorClass{Timeout}, httpCode(200) {}
constexpr ConnectionError(ErrorClass e, long httpCode) : errorClass{e}, httpCode(httpCode) {}
constexpr const char * what() const {
return errorClassPrettyName[static_cast< int >(errorClass)].data();
}
ErrorClass errorClass;
long httpCode;
};
class CoreHandlerError {
public:
enum ErrorClass { BadSigature, RublonCoreException, BrokenData, APIException, TransactionException };
constexpr static auto errorClassPrettyName =
make_array("BadSigature", "RublonCoreException", "BrokenData", "APIException", "TransactionException");
constexpr static auto prettyName = "Core Handler Error";
// APIException -> code: 10
// TransactionException -> code: 11
CoreHandlerError(ErrorClass e = BadSigature, std::string r = "") : errorClass{e}, reson{std::move(r)} {}
constexpr const char * what() const {
return errorClassPrettyName[static_cast< int >(errorClass)].data();
}
ErrorClass errorClass;
std::string reson; // TODO dynamic mem
};
class MethodError {
public:
enum ErrorClass { BadMethod, BadUserInput, NoMethodAvailable };
constexpr static auto errorClassPrettyName = make_array("BadMethod", "BadUserInput", "NoMethodAvailable");
constexpr static auto prettyName = "Method Error";
constexpr MethodError(ErrorClass e = BadMethod) : errorClass{e} {}
constexpr const char * what() const {
return errorClassPrettyName[static_cast< int >(errorClass)].data();
}
ErrorClass errorClass;
};
class WerificationError {
public:
enum ErrorClass {
BadInput, // User input has incorrect characters or length
PasscodeException // Exception from core
};
constexpr static auto errorClassPrettyName = make_array("BadInput", "PasscodeException");
constexpr static inline auto prettyName = "Werification Error";
constexpr WerificationError(ErrorClass e = PasscodeException) : errorClass{e} {}
constexpr const char * what() const {
return errorClassPrettyName[static_cast< int >(errorClass)].data();
}
static std::optional< WerificationError > fromString(std::string_view name) {
for(std::size_t i{}; i < errorClassPrettyName.size(); i++) {
if(errorClassPrettyName.at(i) == name) {
return std::make_optional(WerificationError{static_cast< ErrorClass >(i)});
}
}
return std::nullopt;
}
ErrorClass errorClass;
};
class RublonAuthenticationInterrupt {
public:
enum ErrorClass { UserBaypass, UserDenied, UserPending, UserWaiting, UserNotFound };
constexpr static auto errorClassPrettyName =
make_array("UserBypassedException", "UserDenied", "UserPending", "UserWaiting", "UserNotFoundException");
constexpr static auto prettyName = "Rublon Authentication Interrupt";
RublonAuthenticationInterrupt(ErrorClass e = UserBaypass) : errorClass{e} {}
constexpr const char * what() const {
return errorClassPrettyName[static_cast< int >(errorClass)].data();
}
static std::optional< RublonAuthenticationInterrupt > fromString(std::string_view name) {
for(std::size_t i{}; i < errorClassPrettyName.size(); i++) {
if(errorClassPrettyName.at(i) == name) {
return std::make_optional(RublonAuthenticationInterrupt{static_cast< ErrorClass >(i)});
}
}
return std::nullopt;
}
ErrorClass errorClass;
};
class RublonCheckApplicationException {
public:
enum ErrorClass { ApplicationNotFoundException, InvalidSignatureException, UnsupportedVersionException };
constexpr static auto errorClassPrettyName =
make_array("ApplicationNotFoundException", "InvalidSignatureException", "UnsupportedVersionException");
constexpr static auto prettyName = "Rublon Check Application Interrupt";
RublonCheckApplicationException(ErrorClass e = ApplicationNotFoundException) : errorClass{e} {}
constexpr const char * what() const {
return errorClassPrettyName[static_cast< int >(errorClass)].data();
}
static std::optional< RublonCheckApplicationException > fromString(std::string_view name) {
for(std::size_t i{}; i < errorClassPrettyName.size(); i++) {
if(errorClassPrettyName.at(i) == name) {
return std::make_optional(RublonCheckApplicationException{static_cast< ErrorClass >(i)});
}
}
return std::nullopt;
}
ErrorClass errorClass;
};
class Error {
using Error_t = std::variant< ConfigurationError,
CoreHandlerError,
ConnectionError,
WerificationError,
MethodError,
RublonAuthenticationInterrupt,
RublonCheckApplicationException >;
Error_t _error;
public:
enum Category {
k_ConfigurationError,
k_CoreHandlerError,
k_ConnectionError,
k_WerificationError,
k_MethodError,
k_RublonAuthenticationInterrupt,
k_RublonCheckApplication
};
Error() = default;
Error(ConfigurationError error) : _error{error} {}
Error(CoreHandlerError error) : _error{error} {}
Error(ConnectionError error) : _error{error} {}
Error(MethodError error) : _error{error} {}
Error(WerificationError error) : _error{error} {}
Error(RublonAuthenticationInterrupt error) : _error{error} {}
Error(RublonCheckApplicationException error) : _error{error} {}
Error(const Error &) = default;
Error(Error &&) = default;
Error & operator=(const Error &) = default;
Error & operator=(Error &&) = default;
public:
constexpr bool coreError() const {
return _error.index() == 1;
}
constexpr bool sockerError() const {
return _error.index() == 2;
}
constexpr Category category() const noexcept {
return static_cast< Category >(_error.index());
}
constexpr const char * categoryName() const noexcept {
return std::visit([](const auto & e) { return e.what(); }, _error);
}
constexpr int errorClass() const noexcept {
return std::visit([](const auto & e) { return static_cast< int >(e.errorClass); }, _error);
}
constexpr const char * errorClassName() const noexcept {
return std::visit([](const auto & e) { return e.prettyName; }, _error);
}
template < typename E >
constexpr bool is() const {
return category() == Error{E{}}.category();
}
template < typename E >
constexpr bool is(typename E::ErrorClass errorClass) const {
return is< E >() && hasSameErrorClassAs(errorClass);
}
template < typename E >
constexpr bool isSameCategoryAs(const E & e) const {
return category() == Error{e}.category();
}
constexpr bool hasClass(int _class) const {
return errorClass() == _class;
}
template < typename E >
constexpr bool hasSameErrorClassAs(E e) const {
assert(isSameCategoryAs(e));
return errorClass() == Error{e}.errorClass();
}
template < typename E >
constexpr const E & get() const {
return std::get< E >(_error);
}
};
constexpr bool operator==(const Error & e, const ConnectionError & socket) {
return e.sockerError() && e.errorClass() == socket.errorClass;
}
template < typename T >
constexpr bool operator==(const Error & lhs, const T & rhs) {
return lhs.isSameCategoryAs(rhs) && lhs.hasSameErrorClassAs(rhs);
}
} // namespace rublon