mirror of
https://github.com/IT4Change/gradido.git
synced 2025-12-13 07:45:54 +00:00
Add email_hash to user db, model::table::user and a json interface to search for publickey by email hash
This commit is contained in:
parent
b8b289f793
commit
d0b4a5f2c2
8
README
8
README
@ -21,16 +21,18 @@ cd ../../../
|
||||
|
||||
|
||||
cd dependencies/grpc
|
||||
mkdir _build
|
||||
cd _build
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
make
|
||||
# under windows build at least release for protoc.exe and grpc c++ plugin
|
||||
cd ../../../
|
||||
./unix_parse_proto.sh
|
||||
|
||||
# get more dependencies with conan (need conan from https://conan.io/)
|
||||
mkdir build && cd build
|
||||
conan remote add inexor https://api.bintray.com/conan/inexorgame/inexor-conan
|
||||
# // not used anymore
|
||||
# conan remote add inexor https://api.bintray.com/conan/inexorgame/inexor-conan
|
||||
# conan install .. -s build_type=Debug
|
||||
conan install ..
|
||||
|
||||
|
||||
@ -6,6 +6,7 @@ CREATE TABLE `users` (
|
||||
`password` bigint unsigned NOT NULL,
|
||||
`pubkey` binary(32) DEFAULT NULL,
|
||||
`privkey` binary(80) DEFAULT NULL,
|
||||
`email_hash` binary(32) DEFAULT NULL,
|
||||
`created` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`email_checked` tinyint NOT NULL DEFAULT '0',
|
||||
`passphrase_shown` tinyint NOT NULL DEFAULT '0',
|
||||
|
||||
@ -1,267 +1,263 @@
|
||||
#include "Gradido_LoginServer.h"
|
||||
#include "ServerConfig.h"
|
||||
#include "HTTPInterface/PageRequestHandlerFactory.h"
|
||||
#include "JSONInterface/JsonRequestHandlerFactory.h"
|
||||
|
||||
#include "lib/Profiler.h"
|
||||
|
||||
#include "SingletonManager/ConnectionManager.h"
|
||||
#include "SingletonManager/SessionManager.h"
|
||||
#include "SingletonManager/EmailManager.h"
|
||||
|
||||
#include "controller/User.h"
|
||||
|
||||
#include "Poco/Util/HelpFormatter.h"
|
||||
#include "Poco/Net/ServerSocket.h"
|
||||
#include "Poco/Net/HTTPServer.h"
|
||||
#include "Poco/Net/SSLManager.h"
|
||||
#include "Poco/Environment.h"
|
||||
#include "Poco/Logger.h"
|
||||
#include "Poco/Path.h"
|
||||
#include "Poco/AsyncChannel.h"
|
||||
#include "Poco/SimpleFileChannel.h"
|
||||
#include "Poco/ConsoleChannel.h"
|
||||
#include "Poco/SplitterChannel.h"
|
||||
#include "MySQL/Poco/Connector.h"
|
||||
|
||||
|
||||
#include <sodium.h>
|
||||
|
||||
|
||||
|
||||
Gradido_LoginServer::Gradido_LoginServer()
|
||||
: _helpRequested(false)
|
||||
{
|
||||
}
|
||||
|
||||
Gradido_LoginServer::~Gradido_LoginServer()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void Gradido_LoginServer::initialize(Application& self)
|
||||
{
|
||||
loadConfiguration(); // load default configuration files, if present
|
||||
ServerApplication::initialize(self);
|
||||
}
|
||||
|
||||
void Gradido_LoginServer::uninitialize()
|
||||
{
|
||||
ServerApplication::uninitialize();
|
||||
}
|
||||
|
||||
void Gradido_LoginServer::defineOptions(Poco::Util::OptionSet& options)
|
||||
{
|
||||
ServerApplication::defineOptions(options);
|
||||
|
||||
/*options.addOption(
|
||||
Poco::Util::Option("help", "h", "display help information on command line arguments")
|
||||
.required(false)
|
||||
.repeatable(false));*/
|
||||
options.addOption(
|
||||
Poco::Util::Option("config", "c", "use non default config file (default is /etc/grd_login.properties)", false)
|
||||
.repeatable(false)
|
||||
.argument("Gradido_LoginServer.properties", true)
|
||||
.callback(Poco::Util::OptionCallback<Gradido_LoginServer>(this, &Gradido_LoginServer::handleOption)));
|
||||
|
||||
}
|
||||
|
||||
void Gradido_LoginServer::handleOption(const std::string& name, const std::string& value)
|
||||
{
|
||||
//printf("handle option: %s with value: %s\n", name.data(), value.data());
|
||||
if (name == "config") {
|
||||
mConfigPath = value;
|
||||
return;
|
||||
}
|
||||
ServerApplication::handleOption(name, value);
|
||||
if (name == "help") _helpRequested = true;
|
||||
|
||||
}
|
||||
|
||||
void Gradido_LoginServer::displayHelp()
|
||||
{
|
||||
Poco::Util::HelpFormatter helpFormatter(options());
|
||||
helpFormatter.setCommand(commandName());
|
||||
helpFormatter.setUsage("OPTIONS");
|
||||
helpFormatter.setHeader("Gradido Login Server");
|
||||
helpFormatter.format(std::cout);
|
||||
}
|
||||
|
||||
void Gradido_LoginServer::createConsoleFileAsyncLogger(std::string name, std::string filePath)
|
||||
{
|
||||
Poco::AutoPtr<Poco::ConsoleChannel> logConsoleChannel(new Poco::ConsoleChannel);
|
||||
Poco::AutoPtr<Poco::SimpleFileChannel> logFileChannel(new Poco::SimpleFileChannel(filePath));
|
||||
logFileChannel->setProperty("rotation", "500 K");
|
||||
Poco::AutoPtr<Poco::SplitterChannel> logSplitter(new Poco::SplitterChannel);
|
||||
logSplitter->addChannel(logConsoleChannel);
|
||||
logSplitter->addChannel(logFileChannel);
|
||||
|
||||
Poco::AutoPtr<Poco::AsyncChannel> logAsyncChannel(new Poco::AsyncChannel(logSplitter));
|
||||
|
||||
Poco::Logger& log = Poco::Logger::get(name);
|
||||
log.setChannel(logAsyncChannel);
|
||||
log.setLevel("information");
|
||||
}
|
||||
|
||||
int Gradido_LoginServer::main(const std::vector<std::string>& args)
|
||||
{
|
||||
|
||||
Profiler usedTime;
|
||||
if (_helpRequested)
|
||||
{
|
||||
displayHelp();
|
||||
}
|
||||
else
|
||||
{
|
||||
// ********** logging ************************************
|
||||
std::string log_Path = "/var/log/grd_login/";
|
||||
//#ifdef _WIN32
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
log_Path = "./";
|
||||
#endif
|
||||
|
||||
// init speed logger
|
||||
Poco::AutoPtr<Poco::SimpleFileChannel> speedLogFileChannel(new Poco::SimpleFileChannel(log_Path + "speedLog.txt"));
|
||||
/*
|
||||
The optional log file rotation mode:
|
||||
never: no rotation (default)
|
||||
<n>: rotate if file size exceeds <n> bytes
|
||||
<n> K: rotate if file size exceeds <n> Kilobytes
|
||||
<n> M: rotate if file size exceeds <n> Megabytes
|
||||
*/
|
||||
speedLogFileChannel->setProperty("rotation", "500 K");
|
||||
Poco::AutoPtr<Poco::AsyncChannel> speedLogAsyncChannel(new Poco::AsyncChannel(speedLogFileChannel));
|
||||
|
||||
Poco::Logger& speedLogger = Poco::Logger::get("SpeedLog");
|
||||
speedLogger.setChannel(speedLogAsyncChannel);
|
||||
speedLogger.setLevel("information");
|
||||
|
||||
// logging for request handling
|
||||
createConsoleFileAsyncLogger("requestLog", log_Path + "requestLog.txt");
|
||||
|
||||
// error logging
|
||||
createConsoleFileAsyncLogger("errorLog", log_Path + "errorLog.txt");
|
||||
Poco::Logger& errorLog = Poco::Logger::get("errorLog");
|
||||
|
||||
createConsoleFileAsyncLogger("emailLog", log_Path + "emailLog.txt");
|
||||
|
||||
// *************** load from config ********************************************
|
||||
|
||||
std::string cfg_Path = Poco::Path::config() + "grd_login/grd_login.properties";
|
||||
if (mConfigPath != "") {
|
||||
cfg_Path = mConfigPath;
|
||||
}
|
||||
|
||||
try {
|
||||
loadConfiguration(cfg_Path);
|
||||
}
|
||||
catch (Poco::Exception& ex) {
|
||||
errorLog.error("error loading config: %s from path: %s", ex.displayText(), cfg_Path);
|
||||
}
|
||||
|
||||
unsigned short port = (unsigned short)config().getInt("HTTPServer.port", 9980);
|
||||
unsigned short json_port = (unsigned short)config().getInt("JSONServer.port", 1201);
|
||||
|
||||
|
||||
//printf("show mnemonic list: \n");
|
||||
//printf(ServerConfig::g_Mnemonic_WordLists[ServerConfig::MNEMONIC_BIP0039_SORTED_ORDER].getCompleteWordList().data());
|
||||
if (!ServerConfig::initServerCrypto(config())) {
|
||||
//printf("[Gradido_LoginServer::%s] error init server crypto\n", __FUNCTION__);
|
||||
errorLog.error("[Gradido_LoginServer::main] error init server crypto");
|
||||
return Application::EXIT_CONFIG;
|
||||
}
|
||||
|
||||
// first check time for crypto
|
||||
auto testUser = new User("email@google.de", "Max", "Mustermann");
|
||||
Profiler timeUsed;
|
||||
testUser->validatePwd("haz27Newpassword", nullptr);
|
||||
ServerConfig::g_FakeLoginSleepTime = (int)std::round(timeUsed.millis());
|
||||
delete testUser;
|
||||
|
||||
Poco::Int64 i1 = randombytes_random();
|
||||
Poco::Int64 i2 = randombytes_random();
|
||||
ServerConfig::g_ServerKeySeed->put(1, i1 | (i2 << 8));
|
||||
|
||||
ServerConfig::initEMailAccount(config());
|
||||
EmailManager::getInstance()->init(config());
|
||||
|
||||
// start cpu scheduler
|
||||
uint8_t worker_count = Poco::Environment::processorCount() * 2;
|
||||
|
||||
ServerConfig::g_CPUScheduler = new UniLib::controller::CPUSheduler(worker_count, "Default Worker");
|
||||
ServerConfig::g_CryptoCPUScheduler = new UniLib::controller::CPUSheduler(2, "Crypto Worker");
|
||||
|
||||
// load up connection configs
|
||||
// register MySQL connector
|
||||
Poco::Data::MySQL::Connector::registerConnector();
|
||||
//Poco::Data::MySQL::Connector::KEY;
|
||||
auto conn = ConnectionManager::getInstance();
|
||||
//conn->setConnection()
|
||||
//printf("try connect login server mysql db\n");
|
||||
try {
|
||||
conn->setConnectionsFromConfig(config(), CONNECTION_MYSQL_LOGIN_SERVER);
|
||||
}
|
||||
catch (Poco::Exception& ex) {
|
||||
// maybe we in docker environment and db needs some time to start up
|
||||
// let's wait 10 seconds
|
||||
int count = 10;
|
||||
while (count > 0) {
|
||||
printf("\rwait on mysql/mariadb %d seconds...", count);
|
||||
count--;
|
||||
Poco::Thread::sleep(1000);
|
||||
}
|
||||
conn->setConnectionsFromConfig(config(), CONNECTION_MYSQL_LOGIN_SERVER);
|
||||
}
|
||||
//printf("try connect php server mysql \n");
|
||||
//conn->setConnectionsFromConfig(config(), CONNECTION_MYSQL_PHP_SERVER);
|
||||
|
||||
SessionManager::getInstance()->init();
|
||||
// put urandom on linux servers
|
||||
//srand();
|
||||
|
||||
Poco::Net::initializeSSL();
|
||||
if(!ServerConfig::initSSLClientContext()) {
|
||||
//printf("[Gradido_LoginServer::%s] error init server SSL Client\n", __FUNCTION__);
|
||||
errorLog.error("[Gradido_LoginServer::main] error init server SSL Client\n");
|
||||
return Application::EXIT_CONFIG;
|
||||
}
|
||||
|
||||
// schedule email verification resend
|
||||
controller::User::checkIfVerificationEmailsShouldBeResend(ServerConfig::g_CronJobsTimer);
|
||||
|
||||
// HTTP Interface Server
|
||||
// set-up a server socket
|
||||
Poco::Net::ServerSocket svs(port);
|
||||
// set-up a HTTPServer instance
|
||||
Poco::ThreadPool& pool = Poco::ThreadPool::defaultPool();
|
||||
Poco::Net::HTTPServer srv(new PageRequestHandlerFactory, svs, new Poco::Net::HTTPServerParams);
|
||||
ServerConfig::g_ServerKeySeed->put(7, 918276611);
|
||||
|
||||
// start the HTTPServer
|
||||
srv.start();
|
||||
|
||||
// JSON Interface Server
|
||||
Poco::Net::ServerSocket json_svs(json_port);
|
||||
Poco::Net::HTTPServer json_srv(new JsonRequestHandlerFactory, json_svs, new Poco::Net::HTTPServerParams);
|
||||
|
||||
// start the json server
|
||||
json_srv.start();
|
||||
|
||||
printf("[Gradido_LoginServer::main] started in %s\n", usedTime.string().data());
|
||||
// wait for CTRL-C or kill
|
||||
waitForTerminationRequest();
|
||||
|
||||
// Stop the HTTPServer
|
||||
srv.stop();
|
||||
// Stop the json server
|
||||
json_srv.stop();
|
||||
|
||||
ServerConfig::unload();
|
||||
Poco::Net::uninitializeSSL();
|
||||
// Optional: Delete all global objects allocated by libprotobuf.
|
||||
google::protobuf::ShutdownProtobufLibrary();
|
||||
|
||||
}
|
||||
return Application::EXIT_OK;
|
||||
}
|
||||
|
||||
#include "Gradido_LoginServer.h"
|
||||
#include "ServerConfig.h"
|
||||
#include "HTTPInterface/PageRequestHandlerFactory.h"
|
||||
#include "JSONInterface/JsonRequestHandlerFactory.h"
|
||||
|
||||
#include "lib/Profiler.h"
|
||||
|
||||
#include "SingletonManager/ConnectionManager.h"
|
||||
#include "SingletonManager/SessionManager.h"
|
||||
#include "SingletonManager/EmailManager.h"
|
||||
|
||||
#include "controller/User.h"
|
||||
|
||||
#include "Poco/Util/HelpFormatter.h"
|
||||
#include "Poco/Net/ServerSocket.h"
|
||||
#include "Poco/Net/HTTPServer.h"
|
||||
#include "Poco/Net/SSLManager.h"
|
||||
#include "Poco/Environment.h"
|
||||
#include "Poco/Logger.h"
|
||||
#include "Poco/Path.h"
|
||||
#include "Poco/AsyncChannel.h"
|
||||
#include "Poco/SimpleFileChannel.h"
|
||||
#include "Poco/ConsoleChannel.h"
|
||||
#include "Poco/SplitterChannel.h"
|
||||
#include "MySQL/Poco/Connector.h"
|
||||
|
||||
|
||||
#include <sodium.h>
|
||||
|
||||
|
||||
|
||||
Gradido_LoginServer::Gradido_LoginServer()
|
||||
: _helpRequested(false)
|
||||
{
|
||||
}
|
||||
|
||||
Gradido_LoginServer::~Gradido_LoginServer()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void Gradido_LoginServer::initialize(Application& self)
|
||||
{
|
||||
loadConfiguration(); // load default configuration files, if present
|
||||
ServerApplication::initialize(self);
|
||||
}
|
||||
|
||||
void Gradido_LoginServer::uninitialize()
|
||||
{
|
||||
ServerApplication::uninitialize();
|
||||
}
|
||||
|
||||
void Gradido_LoginServer::defineOptions(Poco::Util::OptionSet& options)
|
||||
{
|
||||
ServerApplication::defineOptions(options);
|
||||
|
||||
/*options.addOption(
|
||||
Poco::Util::Option("help", "h", "display help information on command line arguments")
|
||||
.required(false)
|
||||
.repeatable(false));*/
|
||||
options.addOption(
|
||||
Poco::Util::Option("config", "c", "use non default config file (default is /etc/grd_login.properties)", false)
|
||||
.repeatable(false)
|
||||
.argument("Gradido_LoginServer.properties", true)
|
||||
.callback(Poco::Util::OptionCallback<Gradido_LoginServer>(this, &Gradido_LoginServer::handleOption)));
|
||||
|
||||
}
|
||||
|
||||
void Gradido_LoginServer::handleOption(const std::string& name, const std::string& value)
|
||||
{
|
||||
//printf("handle option: %s with value: %s\n", name.data(), value.data());
|
||||
if (name == "config") {
|
||||
mConfigPath = value;
|
||||
return;
|
||||
}
|
||||
ServerApplication::handleOption(name, value);
|
||||
if (name == "help") _helpRequested = true;
|
||||
}
|
||||
|
||||
void Gradido_LoginServer::displayHelp()
|
||||
{
|
||||
Poco::Util::HelpFormatter helpFormatter(options());
|
||||
helpFormatter.setCommand(commandName());
|
||||
helpFormatter.setUsage("OPTIONS");
|
||||
helpFormatter.setHeader("Gradido Login Server");
|
||||
helpFormatter.format(std::cout);
|
||||
}
|
||||
|
||||
void Gradido_LoginServer::createConsoleFileAsyncLogger(std::string name, std::string filePath)
|
||||
{
|
||||
Poco::AutoPtr<Poco::ConsoleChannel> logConsoleChannel(new Poco::ConsoleChannel);
|
||||
Poco::AutoPtr<Poco::SimpleFileChannel> logFileChannel(new Poco::SimpleFileChannel(filePath));
|
||||
logFileChannel->setProperty("rotation", "500 K");
|
||||
Poco::AutoPtr<Poco::SplitterChannel> logSplitter(new Poco::SplitterChannel);
|
||||
logSplitter->addChannel(logConsoleChannel);
|
||||
logSplitter->addChannel(logFileChannel);
|
||||
|
||||
Poco::AutoPtr<Poco::AsyncChannel> logAsyncChannel(new Poco::AsyncChannel(logSplitter));
|
||||
|
||||
Poco::Logger& log = Poco::Logger::get(name);
|
||||
log.setChannel(logAsyncChannel);
|
||||
log.setLevel("information");
|
||||
}
|
||||
|
||||
int Gradido_LoginServer::main(const std::vector<std::string>& args)
|
||||
{
|
||||
Profiler usedTime;
|
||||
if (_helpRequested)
|
||||
{
|
||||
displayHelp();
|
||||
}
|
||||
else
|
||||
{
|
||||
// ********** logging ************************************
|
||||
std::string log_Path = "/var/log/grd_login/";
|
||||
//#ifdef _WIN32
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
log_Path = "./";
|
||||
#endif
|
||||
|
||||
// init speed logger
|
||||
Poco::AutoPtr<Poco::SimpleFileChannel> speedLogFileChannel(new Poco::SimpleFileChannel(log_Path + "speedLog.txt"));
|
||||
/*
|
||||
The optional log file rotation mode:
|
||||
never: no rotation (default)
|
||||
<n>: rotate if file size exceeds <n> bytes
|
||||
<n> K: rotate if file size exceeds <n> Kilobytes
|
||||
<n> M: rotate if file size exceeds <n> Megabytes
|
||||
*/
|
||||
speedLogFileChannel->setProperty("rotation", "500 K");
|
||||
Poco::AutoPtr<Poco::AsyncChannel> speedLogAsyncChannel(new Poco::AsyncChannel(speedLogFileChannel));
|
||||
|
||||
Poco::Logger& speedLogger = Poco::Logger::get("SpeedLog");
|
||||
speedLogger.setChannel(speedLogAsyncChannel);
|
||||
speedLogger.setLevel("information");
|
||||
|
||||
// logging for request handling
|
||||
createConsoleFileAsyncLogger("requestLog", log_Path + "requestLog.txt");
|
||||
|
||||
// error logging
|
||||
createConsoleFileAsyncLogger("errorLog", log_Path + "errorLog.txt");
|
||||
Poco::Logger& errorLog = Poco::Logger::get("errorLog");
|
||||
|
||||
createConsoleFileAsyncLogger("emailLog", log_Path + "emailLog.txt");
|
||||
|
||||
// *************** load from config ********************************************
|
||||
|
||||
std::string cfg_Path = Poco::Path::config() + "grd_login/";
|
||||
try {
|
||||
loadConfiguration(cfg_Path + "grd_login.properties");
|
||||
}
|
||||
catch (Poco::Exception& ex) {
|
||||
errorLog.error("error loading config: %s", ex.displayText());
|
||||
}
|
||||
|
||||
unsigned short port = (unsigned short)config().getInt("HTTPServer.port", 9980);
|
||||
unsigned short json_port = (unsigned short)config().getInt("JSONServer.port", 1201);
|
||||
|
||||
|
||||
//printf("show mnemonic list: \n");
|
||||
//printf(ServerConfig::g_Mnemonic_WordLists[ServerConfig::MNEMONIC_BIP0039_SORTED_ORDER].getCompleteWordList().data());
|
||||
if (!ServerConfig::initServerCrypto(config())) {
|
||||
//printf("[Gradido_LoginServer::%s] error init server crypto\n", __FUNCTION__);
|
||||
errorLog.error("[Gradido_LoginServer::main] error init server crypto");
|
||||
return Application::EXIT_CONFIG;
|
||||
}
|
||||
|
||||
// first check time for crypto
|
||||
auto testUser = new User("email@google.de", "Max", "Mustermann");
|
||||
Profiler timeUsed;
|
||||
testUser->validatePwd("haz27Newpassword", nullptr);
|
||||
ServerConfig::g_FakeLoginSleepTime = (int)std::round(timeUsed.millis());
|
||||
delete testUser;
|
||||
|
||||
Poco::Int64 i1 = randombytes_random();
|
||||
Poco::Int64 i2 = randombytes_random();
|
||||
ServerConfig::g_ServerKeySeed->put(1, i1 | (i2 << 8));
|
||||
|
||||
ServerConfig::initEMailAccount(config());
|
||||
EmailManager::getInstance()->init(config());
|
||||
|
||||
// start cpu scheduler
|
||||
uint8_t worker_count = Poco::Environment::processorCount() * 2;
|
||||
|
||||
ServerConfig::g_CPUScheduler = new UniLib::controller::CPUSheduler(worker_count, "Default Worker");
|
||||
ServerConfig::g_CryptoCPUScheduler = new UniLib::controller::CPUSheduler(2, "Crypto Worker");
|
||||
|
||||
// load up connection configs
|
||||
// register MySQL connector
|
||||
Poco::Data::MySQL::Connector::registerConnector();
|
||||
//Poco::Data::MySQL::Connector::KEY;
|
||||
auto conn = ConnectionManager::getInstance();
|
||||
//conn->setConnection()
|
||||
//printf("try connect login server mysql db\n");
|
||||
try {
|
||||
conn->setConnectionsFromConfig(config(), CONNECTION_MYSQL_LOGIN_SERVER);
|
||||
}
|
||||
catch (Poco::Exception& ex) {
|
||||
// maybe we in docker environment and db needs some time to start up
|
||||
// let's wait 10 seconds
|
||||
int count = 10;
|
||||
while (count > 0) {
|
||||
printf("\rwait on mysql/mariadb %d seconds...", count);
|
||||
count--;
|
||||
Poco::Thread::sleep(1000);
|
||||
}
|
||||
conn->setConnectionsFromConfig(config(), CONNECTION_MYSQL_LOGIN_SERVER);
|
||||
}
|
||||
//printf("try connect php server mysql \n");
|
||||
//conn->setConnectionsFromConfig(config(), CONNECTION_MYSQL_PHP_SERVER);
|
||||
|
||||
SessionManager::getInstance()->init();
|
||||
// put urandom on linux servers
|
||||
//srand();
|
||||
|
||||
Poco::Net::initializeSSL();
|
||||
if(!ServerConfig::initSSLClientContext()) {
|
||||
//printf("[Gradido_LoginServer::%s] error init server SSL Client\n", __FUNCTION__);
|
||||
errorLog.error("[Gradido_LoginServer::main] error init server SSL Client\n");
|
||||
return Application::EXIT_CONFIG;
|
||||
}
|
||||
|
||||
// schedule email verification resend
|
||||
controller::User::checkIfVerificationEmailsShouldBeResend(ServerConfig::g_CronJobsTimer);
|
||||
controller::User::addMissingEmailHashes();
|
||||
|
||||
// HTTP Interface Server
|
||||
// set-up a server socket
|
||||
Poco::Net::ServerSocket svs(port);
|
||||
// set-up a HTTPServer instance
|
||||
Poco::ThreadPool& pool = Poco::ThreadPool::defaultPool();
|
||||
Poco::Net::HTTPServer srv(new PageRequestHandlerFactory, svs, new Poco::Net::HTTPServerParams);
|
||||
ServerConfig::g_ServerKeySeed->put(7, 918276611);
|
||||
|
||||
// start the HTTPServer
|
||||
srv.start();
|
||||
|
||||
// JSON Interface Server
|
||||
Poco::Net::ServerSocket json_svs(json_port);
|
||||
Poco::Net::HTTPServer json_srv(new JsonRequestHandlerFactory, json_svs, new Poco::Net::HTTPServerParams);
|
||||
|
||||
// start the json server
|
||||
json_srv.start();
|
||||
|
||||
printf("[Gradido_LoginServer::main] started in %s\n", usedTime.string().data());
|
||||
// wait for CTRL-C or kill
|
||||
waitForTerminationRequest();
|
||||
|
||||
// Stop the HTTPServer
|
||||
srv.stop();
|
||||
// Stop the json server
|
||||
json_srv.stop();
|
||||
|
||||
ServerConfig::unload();
|
||||
Poco::Net::uninitializeSSL();
|
||||
// Optional: Delete all global objects allocated by libprotobuf.
|
||||
google::protobuf::ShutdownProtobufLibrary();
|
||||
|
||||
}
|
||||
return Application::EXIT_OK;
|
||||
}
|
||||
|
||||
>>>>>>> 419965f (Add email_hash to user db, model::table::user and a json interface to search for publickey by email hash)
|
||||
|
||||
@ -1,74 +1,78 @@
|
||||
#include "JsonRequestHandlerFactory.h"
|
||||
|
||||
#include "Poco/Net/HTTPServerRequest.h"
|
||||
|
||||
#include "../SingletonManager/SessionManager.h"
|
||||
|
||||
#include "JsonCreateUser.h"
|
||||
#include "JsonGetLogin.h"
|
||||
#include "JsonUnknown.h"
|
||||
#include "JsonTransaction.h"
|
||||
#include "JsonGetRunningUserTasks.h"
|
||||
#include "JsonGetUsers.h"
|
||||
#include "JsonAdminEmailVerificationResend.h"
|
||||
#include "JsonGetUserInfos.h"
|
||||
#include "JsonUpdateUserInfos.h"
|
||||
#include "JsonUnsecureLogin.h"
|
||||
#include "JsonLogout.h"
|
||||
|
||||
JsonRequestHandlerFactory::JsonRequestHandlerFactory()
|
||||
: mRemoveGETParameters("^/([a-zA-Z0-9_-]*)"), mLogging(Poco::Logger::get("requestLog"))
|
||||
{
|
||||
}
|
||||
|
||||
Poco::Net::HTTPRequestHandler* JsonRequestHandlerFactory::createRequestHandler(const Poco::Net::HTTPServerRequest& request)
|
||||
{
|
||||
std::string uri = request.getURI();
|
||||
std::string url_first_part;
|
||||
std::stringstream logStream;
|
||||
|
||||
mRemoveGETParameters.extract(uri, url_first_part);
|
||||
|
||||
std::string dateTimeString = Poco::DateTimeFormatter::format(Poco::DateTime(), "%d.%m.%y %H:%M:%S");
|
||||
logStream << dateTimeString << " call " << uri;
|
||||
|
||||
mLogging.information(logStream.str());
|
||||
|
||||
auto client_host = request.clientAddress().host();
|
||||
//auto client_ip = request.clientAddress();
|
||||
// X-Real-IP forwarded ip from nginx config
|
||||
auto client_host_string = request.get("X-Real-IP", client_host.toString());
|
||||
client_host = Poco::Net::IPAddress(client_host_string);
|
||||
|
||||
if (url_first_part == "/login") {
|
||||
return new JsonGetLogin;
|
||||
}
|
||||
else if (url_first_part == "/checkTransaction") {
|
||||
return new JsonTransaction;
|
||||
}
|
||||
else if (url_first_part == "/getRunningUserTasks") {
|
||||
return new JsonGetRunningUserTasks;
|
||||
}
|
||||
else if (url_first_part == "/getUsers") {
|
||||
return new JsonGetUsers;
|
||||
}
|
||||
else if (url_first_part == "/createUser") {
|
||||
return new JsonCreateUser(client_host);
|
||||
}
|
||||
else if (url_first_part == "/adminEmailVerificationResend") {
|
||||
return new JsonAdminEmailVerificationResend;
|
||||
}
|
||||
else if (url_first_part == "/getUserInfos") {
|
||||
return new JsonGetUserInfos;
|
||||
}
|
||||
else if (url_first_part == "/updateUserInfos") {
|
||||
return new JsonUpdateUserInfos;
|
||||
}
|
||||
else if (url_first_part == "/unsecureLogin" && (ServerConfig::g_AllowUnsecureFlags & ServerConfig::UNSECURE_PASSWORD_REQUESTS)) {
|
||||
return new JsonUnsecureLogin(client_host);
|
||||
}
|
||||
else if (url_first_part == "/logout") {
|
||||
return new JsonLogout(client_host);
|
||||
}
|
||||
return new JsonUnknown;
|
||||
}
|
||||
#include "JsonRequestHandlerFactory.h"
|
||||
|
||||
#include "Poco/Net/HTTPServerRequest.h"
|
||||
|
||||
#include "../SingletonManager/SessionManager.h"
|
||||
|
||||
#include "JsonCreateUser.h"
|
||||
#include "JsonGetLogin.h"
|
||||
#include "JsonUnknown.h"
|
||||
#include "JsonTransaction.h"
|
||||
#include "JsonGetRunningUserTasks.h"
|
||||
#include "JsonGetUsers.h"
|
||||
#include "JsonAdminEmailVerificationResend.h"
|
||||
#include "JsonGetUserInfos.h"
|
||||
#include "JsonUpdateUserInfos.h"
|
||||
#include "JsonUnsecureLogin.h"
|
||||
#include "JsonLogout.h"
|
||||
#include "JsonSearch.h"
|
||||
|
||||
JsonRequestHandlerFactory::JsonRequestHandlerFactory()
|
||||
: mRemoveGETParameters("^/([a-zA-Z0-9_-]*)"), mLogging(Poco::Logger::get("requestLog"))
|
||||
{
|
||||
}
|
||||
|
||||
Poco::Net::HTTPRequestHandler* JsonRequestHandlerFactory::createRequestHandler(const Poco::Net::HTTPServerRequest& request)
|
||||
{
|
||||
std::string uri = request.getURI();
|
||||
std::string url_first_part;
|
||||
std::stringstream logStream;
|
||||
|
||||
mRemoveGETParameters.extract(uri, url_first_part);
|
||||
|
||||
std::string dateTimeString = Poco::DateTimeFormatter::format(Poco::DateTime(), "%d.%m.%y %H:%M:%S");
|
||||
logStream << dateTimeString << " call " << uri;
|
||||
|
||||
mLogging.information(logStream.str());
|
||||
|
||||
auto client_host = request.clientAddress().host();
|
||||
//auto client_ip = request.clientAddress();
|
||||
// X-Real-IP forwarded ip from nginx config
|
||||
auto client_host_string = request.get("X-Real-IP", client_host.toString());
|
||||
client_host = Poco::Net::IPAddress(client_host_string);
|
||||
|
||||
if (url_first_part == "/login") {
|
||||
return new JsonGetLogin;
|
||||
}
|
||||
else if (url_first_part == "/checkTransaction") {
|
||||
return new JsonTransaction;
|
||||
}
|
||||
else if (url_first_part == "/getRunningUserTasks") {
|
||||
return new JsonGetRunningUserTasks;
|
||||
}
|
||||
else if (url_first_part == "/getUsers") {
|
||||
return new JsonGetUsers;
|
||||
}
|
||||
else if (url_first_part == "/createUser") {
|
||||
return new JsonCreateUser(client_host);
|
||||
}
|
||||
else if (url_first_part == "/adminEmailVerificationResend") {
|
||||
return new JsonAdminEmailVerificationResend;
|
||||
}
|
||||
else if (url_first_part == "/getUserInfos") {
|
||||
return new JsonGetUserInfos;
|
||||
}
|
||||
else if (url_first_part == "/updateUserInfos") {
|
||||
return new JsonUpdateUserInfos;
|
||||
}
|
||||
else if (url_first_part == "/search") {
|
||||
return new JsonSearch;
|
||||
}
|
||||
else if (url_first_part == "/unsecureLogin" && (ServerConfig::g_AllowUnsecureFlags & ServerConfig::UNSECURE_PASSWORD_REQUESTS)) {
|
||||
return new JsonUnsecureLogin(client_host);
|
||||
}
|
||||
else if (url_first_part == "/logout") {
|
||||
return new JsonLogout(client_host);
|
||||
}
|
||||
return new JsonUnknown;
|
||||
}
|
||||
|
||||
89
src/cpp/JSONInterface/JsonSearch.cpp
Normal file
89
src/cpp/JSONInterface/JsonSearch.cpp
Normal file
@ -0,0 +1,89 @@
|
||||
#include "JsonSearch.h"
|
||||
|
||||
#include "../lib/DataTypeConverter.h"
|
||||
#include "../controller/User.h"
|
||||
#include "../SingletonManager/SessionManager.h"
|
||||
|
||||
Poco::JSON::Object* JsonSearch::handle(Poco::Dynamic::Var params)
|
||||
{
|
||||
/*
|
||||
'ask' = ['account_publickey' => '<email_blake2b_base64>']
|
||||
*/
|
||||
// incoming
|
||||
|
||||
Poco::JSON::Object::Ptr ask;
|
||||
|
||||
// if is json object
|
||||
if (params.type() == typeid(Poco::JSON::Object::Ptr)) {
|
||||
Poco::JSON::Object::Ptr paramJsonObject = params.extract<Poco::JSON::Object::Ptr>();
|
||||
/// Throws a RangeException if the value does not fit
|
||||
/// into the result variable.
|
||||
/// Throws a NotImplementedException if conversion is
|
||||
/// not available for the given type.
|
||||
/// Throws InvalidAccessException if Var is empty.
|
||||
try {
|
||||
ask = paramJsonObject->getObject("ask");
|
||||
}
|
||||
catch (Poco::Exception& ex) {
|
||||
return stateError("json exception", ex.displayText());
|
||||
}
|
||||
}
|
||||
else {
|
||||
return stateError("parameter format unknown");
|
||||
}
|
||||
|
||||
|
||||
if (ask.isNull()) {
|
||||
return stateError("ask is zero or not an object");
|
||||
}
|
||||
|
||||
|
||||
Poco::JSON::Object* result = new Poco::JSON::Object;
|
||||
result->set("state", "success");
|
||||
Poco::JSON::Array jsonErrorsArray;
|
||||
Poco::JSON::Object result_fields;
|
||||
auto sm = SessionManager::getInstance();
|
||||
auto mm = MemoryManager::getInstance();
|
||||
for (auto it = ask->begin(); it != ask->end(); it++) {
|
||||
std::string name = it->first;
|
||||
auto value = it->second;
|
||||
|
||||
|
||||
try {
|
||||
if ("account_publickey" == name) {
|
||||
if (!value.isString()) {
|
||||
jsonErrorsArray.add("account_publickey isn't a string");
|
||||
}
|
||||
else {
|
||||
MemoryBin* email_hash = nullptr;
|
||||
if (sm->isValid(value, VALIDATE_ONLY_HEX)) {
|
||||
email_hash = DataTypeConverter::hexToBin(value);
|
||||
}
|
||||
if (!email_hash) {
|
||||
email_hash = DataTypeConverter::base64ToBin(value);
|
||||
}
|
||||
if (!email_hash) {
|
||||
jsonErrorsArray.add("account_publickey isn't valid base64 or hex");
|
||||
}
|
||||
else {
|
||||
auto user = controller::User::create();
|
||||
user->load(email_hash);
|
||||
mm->releaseMemory(email_hash);
|
||||
auto user_model = user->getModel();
|
||||
auto public_key_base64 = DataTypeConverter::binToBase64(user_model->getPublicKey(), user_model->getPublicKeySize());
|
||||
result_fields.set("account_publickey", public_key_base64);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Poco::Exception& ex) {
|
||||
jsonErrorsArray.add("update parameter invalid");
|
||||
}
|
||||
}
|
||||
|
||||
result->set("errors", jsonErrorsArray);
|
||||
result->set("results", result_fields);
|
||||
result->set("state", "success");
|
||||
|
||||
return result;
|
||||
}
|
||||
24
src/cpp/JSONInterface/JsonSearch.h
Normal file
24
src/cpp/JSONInterface/JsonSearch.h
Normal file
@ -0,0 +1,24 @@
|
||||
#ifndef __JSON_INTERFACE_JSON_SEARCH_
|
||||
#define __JSON_INTERFACE_JSON_SEARCH_
|
||||
|
||||
#include "JsonRequestHandler.h"
|
||||
|
||||
/*!
|
||||
* @author Dario Rekowski
|
||||
* @date 2020-09-28
|
||||
* @brief search for public informations (no session_id needed), like account id for email hash
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
class JsonSearch : public JsonRequestHandler
|
||||
{
|
||||
public:
|
||||
Poco::JSON::Object* handle(Poco::Dynamic::Var params);
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif // __JSON_INTERFACE_JSON_SEARCH_
|
||||
@ -235,7 +235,6 @@ bool SessionManager::releaseSession(int requestHandleSession)
|
||||
mWorkingMutex.unlock();
|
||||
return false;
|
||||
}
|
||||
|
||||
Session* session = it->second;
|
||||
|
||||
|
||||
@ -246,6 +245,7 @@ bool SessionManager::releaseSession(int requestHandleSession)
|
||||
return true;
|
||||
|
||||
|
||||
|
||||
// check if dead locked
|
||||
if (session->tryLock()) {
|
||||
session->unlock();
|
||||
|
||||
@ -83,6 +83,11 @@ namespace controller {
|
||||
return getModel()->loadFromDB("pubkey", pubkey);
|
||||
}
|
||||
|
||||
int User::load(MemoryBin* emailHash)
|
||||
{
|
||||
Poco::Data::BLOB email_hash(*emailHash, crypto_generichash_BYTES);
|
||||
return getModel()->loadFromDB("email_hash", email_hash);
|
||||
}
|
||||
const std::string& User::getPublicHex()
|
||||
{
|
||||
if (mPublicHex != "") {
|
||||
@ -404,4 +409,60 @@ namespace controller {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int User::addMissingEmailHashes()
|
||||
{
|
||||
auto cm = ConnectionManager::getInstance();
|
||||
auto em = ErrorManager::getInstance();
|
||||
static const char* function_name = "User::addMissingEmailHashes";
|
||||
|
||||
auto session = cm->getConnection(CONNECTION_MYSQL_LOGIN_SERVER);
|
||||
Poco::Data::Statement select(session);
|
||||
std::vector<Poco::Tuple<int, std::string>> results;
|
||||
|
||||
select << "select id, email from users "
|
||||
<< "where email_hash IS NULL "
|
||||
, Poco::Data::Keywords::into(results)
|
||||
;
|
||||
int result_count = 0;
|
||||
try {
|
||||
result_count = select.execute();
|
||||
}
|
||||
catch (Poco::Exception& ex) {
|
||||
em->addError(new ParamError(function_name, "mysql error by select", ex.displayText().data()));
|
||||
em->sendErrorsAsEmail();
|
||||
//return -1;
|
||||
}
|
||||
if (0 == result_count) return 0;
|
||||
std::vector<Poco::Tuple<Poco::Data::BLOB, int>> updates;
|
||||
// calculate hashes
|
||||
updates.reserve(results.size());
|
||||
unsigned char email_hash[crypto_generichash_BYTES];
|
||||
for (auto it = results.begin(); it != results.end(); it++) {
|
||||
memset(email_hash, 0, crypto_generichash_BYTES);
|
||||
auto id = it->get<0>();
|
||||
auto email = it->get<1>();
|
||||
crypto_generichash(email_hash, crypto_generichash_BYTES,
|
||||
(const unsigned char*)email.data(), email.size(),
|
||||
NULL, 0);
|
||||
updates.push_back(Poco::Tuple<Poco::Data::BLOB, int>(Poco::Data::BLOB(email_hash, crypto_generichash_BYTES), id));
|
||||
}
|
||||
|
||||
// update db
|
||||
// reuse connection, I hope it's working
|
||||
Poco::Data::Statement update(session);
|
||||
update << "UPDATE users set email_hash = ? where id = ?"
|
||||
, Poco::Data::Keywords::use(updates);
|
||||
int updated_count = 0;
|
||||
try {
|
||||
updated_count = update.execute();
|
||||
}
|
||||
catch (Poco::Exception& ex) {
|
||||
em->addError(new ParamError(function_name, "mysql error by update", ex.displayText().data()));
|
||||
em->sendErrorsAsEmail();
|
||||
}
|
||||
return updated_count;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -37,6 +37,9 @@ namespace controller {
|
||||
// TODO: instead scheduling all, scheduling only for next day and run this function every day (own task for that)
|
||||
static int checkIfVerificationEmailsShouldBeResend(const Poco::Util::Timer& timer);
|
||||
|
||||
//! \brief go through whole db and search for user without email hash and set this in db
|
||||
static int addMissingEmailHashes();
|
||||
|
||||
//! \brief try to find correct passphrase for this user from db
|
||||
//!
|
||||
//! select entries from user_backups db table belonging to user
|
||||
@ -53,6 +56,7 @@ namespace controller {
|
||||
//! \return count of found rows, should be 1 or 0
|
||||
inline size_t load(int user_id) { return getModel()->loadFromDB("id", user_id); }
|
||||
int load(const unsigned char* pubkey_array);
|
||||
int load(MemoryBin* emailHash);
|
||||
Poco::JSON::Object getJson();
|
||||
|
||||
inline Poco::AutoPtr<model::table::User> getModel() { return _getModel<model::table::User>(); }
|
||||
|
||||
@ -18,8 +18,9 @@ namespace model {
|
||||
}
|
||||
|
||||
User::User(const std::string& email, const std::string& first_name, const std::string& last_name, Poco::UInt64 passwordHashed/* = 0*/, std::string languageKey/* = "de"*/)
|
||||
: mEmail(email), mFirstName(first_name), mLastName(last_name), mPasswordHashed(passwordHashed), mEmailChecked(false), mLanguageKey(languageKey), mDisabled(false), mRole(ROLE_NOT_LOADED)
|
||||
: mFirstName(first_name), mLastName(last_name), mPasswordHashed(passwordHashed), mEmailChecked(false), mLanguageKey(languageKey), mDisabled(false), mRole(ROLE_NOT_LOADED)
|
||||
{
|
||||
setEmail(email);
|
||||
|
||||
}
|
||||
//id, first_name, last_name, email, pubkey, created, email_checked
|
||||
@ -60,18 +61,31 @@ namespace model {
|
||||
}
|
||||
}
|
||||
|
||||
void User::setEmail(const std::string& email)
|
||||
{
|
||||
std::unique_lock<std::shared_mutex> _lock(mSharedMutex);
|
||||
mEmail = email;
|
||||
|
||||
unsigned char email_hash[crypto_generichash_BYTES];
|
||||
|
||||
crypto_generichash(email_hash, crypto_generichash_BYTES,
|
||||
(const unsigned char*)email.data(), email.size(),
|
||||
NULL, 0);
|
||||
mEmailHash = Poco::Nullable<Poco::Data::BLOB>(Poco::Data::BLOB(email_hash, crypto_generichash_BYTES));
|
||||
}
|
||||
|
||||
Poco::Data::Statement User::_insertIntoDB(Poco::Data::Session session)
|
||||
{
|
||||
Poco::Data::Statement insert(session);
|
||||
|
||||
|
||||
if (mPasswordHashed) {
|
||||
insert << "INSERT INTO users (email, first_name, last_name, password, language) VALUES(?,?,?,?,?);",
|
||||
use(mEmail), use(mFirstName), use(mLastName), bind(mPasswordHashed), use(mLanguageKey);
|
||||
insert << "INSERT INTO users (email, first_name, last_name, password, email_hash, language) VALUES(?,?,?,?,?,?);",
|
||||
use(mEmail), use(mFirstName), use(mLastName), bind(mPasswordHashed), use(mEmailHash), use(mLanguageKey);
|
||||
}
|
||||
else {
|
||||
insert << "INSERT INTO users (email, first_name, last_name, language) VALUES(?,?,?,?);",
|
||||
use(mEmail), use(mFirstName), use(mLastName), use(mLanguageKey);
|
||||
insert << "INSERT INTO users (email, first_name, last_name, email_hash, language) VALUES(?,?,?,?,?);",
|
||||
use(mEmail), use(mFirstName), use(mLastName), use(mEmailHash), use(mLanguageKey);
|
||||
}
|
||||
|
||||
return insert;
|
||||
@ -84,12 +98,12 @@ namespace model {
|
||||
_fieldName = getTableName() + std::string(".id");
|
||||
}
|
||||
Poco::Data::Statement select(session);
|
||||
select << "SELECT " << getTableName() << ".id, email, first_name, last_name, password, pubkey, privkey, created, email_checked, language, disabled, user_roles.role_id "
|
||||
select << "SELECT " << getTableName() << ".id, email, first_name, last_name, password, pubkey, privkey, email_hash, created, email_checked, language, disabled, user_roles.role_id "
|
||||
<< " FROM " << getTableName()
|
||||
<< " LEFT JOIN user_roles ON " << getTableName() << ".id = user_roles.user_id "
|
||||
<< " WHERE " << _fieldName << " = ?" ,
|
||||
into(mID), into(mEmail), into(mFirstName), into(mLastName), into(mPasswordHashed),
|
||||
into(mPublicKey), into(mPrivateKey), into(mCreated), into(mEmailChecked),
|
||||
into(mPublicKey), into(mPrivateKey), into(mEmailHash), into(mCreated), into(mEmailChecked),
|
||||
into(mLanguageKey), into(mDisabled), into(mRole);
|
||||
|
||||
|
||||
@ -266,12 +280,14 @@ namespace model {
|
||||
auto mm = MemoryManager::getInstance();
|
||||
auto pubkeyHex = mm->getFreeMemory(65);
|
||||
auto privkeyHex = mm->getFreeMemory(161);
|
||||
auto email_hash = mm->getFreeMemory(crypto_generichash_BYTES+1);
|
||||
//char pubkeyHex[65], privkeyHex[161];
|
||||
|
||||
//memset(pubkeyHex, 0, 65);
|
||||
//memset(privkeyHex, 0, 161);
|
||||
memset(*pubkeyHex, 0, 65);
|
||||
memset(*privkeyHex, 0, 161);
|
||||
memset(*email_hash, 0, crypto_generichash_BYTES + 1);
|
||||
|
||||
std::stringstream ss;
|
||||
|
||||
@ -281,11 +297,16 @@ namespace model {
|
||||
if (!mPrivateKey.isNull()) {
|
||||
sodium_bin2hex(*privkeyHex, 161, mPrivateKey.value().content().data(), mPrivateKey.value().content().size());
|
||||
}
|
||||
if (!mEmailHash.isNull()) {
|
||||
sodium_bin2hex(*email_hash, crypto_generichash_BYTES + 1, mEmailHash.value().content().data(), mEmailHash.value().content().size());
|
||||
}
|
||||
|
||||
|
||||
ss << mFirstName << " " << mLastName << " <" << mEmail << ">" << std::endl;
|
||||
ss << "password hash: " << mPasswordHashed << std::endl;
|
||||
ss << "public key: " << (char*)*pubkeyHex << std::endl;
|
||||
ss << "private key: " << (char*)*privkeyHex << std::endl;
|
||||
ss << "email hash: " << (char*)*email_hash << std::endl;
|
||||
ss << "created: " << Poco::DateTimeFormatter::format(mCreated, "%f.%m.%Y %H:%M:%S") << std::endl;
|
||||
ss << "email checked: " << mEmailChecked << std::endl;
|
||||
ss << "language key: " << mLanguageKey << std::endl;
|
||||
@ -293,6 +314,7 @@ namespace model {
|
||||
|
||||
mm->releaseMemory(pubkeyHex);
|
||||
mm->releaseMemory(privkeyHex);
|
||||
mm->releaseMemory(email_hash);
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
@ -301,8 +323,10 @@ namespace model {
|
||||
{
|
||||
auto mm = MemoryManager::getInstance();
|
||||
auto pubkeyHex = mm->getFreeMemory(65);
|
||||
auto email_hash = mm->getFreeMemory(crypto_generichash_BYTES + 1);
|
||||
|
||||
memset(*pubkeyHex, 0, 65);
|
||||
memset(*email_hash, 0, crypto_generichash_BYTES + 1);
|
||||
|
||||
std::stringstream ss;
|
||||
|
||||
@ -310,8 +334,13 @@ namespace model {
|
||||
sodium_bin2hex(*pubkeyHex, 65, mPublicKey.value().content().data(), mPublicKey.value().content().size());
|
||||
}
|
||||
|
||||
if (!mEmailHash.isNull()) {
|
||||
sodium_bin2hex(*email_hash, crypto_generichash_BYTES + 1, mEmailHash.value().content().data(), mEmailHash.value().content().size());
|
||||
}
|
||||
|
||||
ss << "<b>" << mFirstName << " " << mLastName << " <" << mEmail << "></b>" << "<br>";
|
||||
ss << "public key: " << (char*)*pubkeyHex << "<br>";
|
||||
ss << "email hash: " << (char*)*email_hash << "<br>";
|
||||
ss << "created: " << Poco::DateTimeFormatter::format(mCreated, "%f.%m.%Y %H:%M:%S") << "<br>";
|
||||
ss << "email checked: " << mEmailChecked << "<br>";
|
||||
ss << "language key: " << mLanguageKey << "<br>";
|
||||
@ -319,6 +348,7 @@ namespace model {
|
||||
ss << "disabled: " << mDisabled << "<br>";
|
||||
|
||||
mm->releaseMemory(pubkeyHex);
|
||||
mm->releaseMemory(email_hash);
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
@ -61,17 +61,19 @@ namespace model {
|
||||
inline std::string getNameWithEmail() const { std::shared_lock<std::shared_mutex> _lock(mSharedMutex); return mFirstName + " " + mLastName + "<" + mEmail + ">"; }
|
||||
inline const Poco::UInt64 getPasswordHashed() const { std::shared_lock<std::shared_mutex> _lock(mSharedMutex); return mPasswordHashed; }
|
||||
inline RoleType getRole() const { std::shared_lock<std::shared_mutex> _lock(mSharedMutex); if (mRole.isNull()) return ROLE_NONE; return static_cast<RoleType>(mRole.value()); }
|
||||
inline const unsigned char* getPublicKey() const { if (mPublicKey.isNull()) return nullptr; return mPublicKey.value().content().data(); }
|
||||
inline const unsigned char* getPublicKey() const { std::shared_lock<std::shared_mutex> _lock(mSharedMutex); if (mPublicKey.isNull()) return nullptr; return mPublicKey.value().content().data(); }
|
||||
inline size_t getPublicKeySize() const { std::shared_lock<std::shared_mutex> _lock(mSharedMutex); if (mPublicKey.isNull()) return 0; return mPublicKey.value().content().size(); }
|
||||
std::string getPublicKeyHex() const;
|
||||
|
||||
inline bool hasPrivateKeyEncrypted() const { std::shared_lock<std::shared_mutex> _lock(mSharedMutex); return !mPrivateKey.isNull(); }
|
||||
inline bool hasEmailHash() const { std::shared_lock<std::shared_mutex> _lock(mSharedMutex); return !mEmailHash.isNull(); }
|
||||
inline const std::vector<unsigned char>& getPrivateKeyEncrypted() const { return mPrivateKey.value().content(); }
|
||||
inline bool isEmailChecked() const { std::shared_lock<std::shared_mutex> _lock(mSharedMutex); return mEmailChecked; }
|
||||
inline const std::string getLanguageKey() const { std::shared_lock<std::shared_mutex> _lock(mSharedMutex); return mLanguageKey; }
|
||||
inline bool isDisabled() const { std::shared_lock<std::shared_mutex> _lock(mSharedMutex); return mDisabled; }
|
||||
|
||||
// default setter unlocked
|
||||
inline void setEmail(const std::string& email) { std::unique_lock<std::shared_mutex> _lock(mSharedMutex); mEmail = email; }
|
||||
void setEmail(const std::string& email);
|
||||
inline void setFirstName(const std::string& first_name) { std::unique_lock<std::shared_mutex> _lock(mSharedMutex); mFirstName = first_name; }
|
||||
inline void setLastName(const std::string& last_name) { std::unique_lock<std::shared_mutex> _lock(mSharedMutex); mLastName = last_name; }
|
||||
inline void setPasswordHashed(const Poco::UInt64& passwordHashed) { std::unique_lock<std::shared_mutex> _lock(mSharedMutex); mPasswordHashed = passwordHashed; }
|
||||
@ -102,6 +104,7 @@ namespace model {
|
||||
|
||||
Poco::Nullable<Poco::Data::BLOB> mPublicKey;
|
||||
Poco::Nullable<Poco::Data::BLOB> mPrivateKey;
|
||||
Poco::Nullable<Poco::Data::BLOB> mEmailHash; // sodium generic hash (currently blake2b)
|
||||
// created: Mysql DateTime
|
||||
Poco::DateTime mCreated;
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user